[gdb/testsuite] Fix license text in gdb.reverse/map-to-same-line.{c,exp}
[binutils-gdb.git] / gprofng / src / DerivedMetrics.cc
blobee14ea01542c09cb2649a224b763625d8c39700a
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
2 Contributed by Oracle.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
21 #include "config.h"
22 #include <strings.h>
23 #include "DerivedMetrics.h"
24 #include "util.h"
26 enum opType
28 opNULL,
29 opPrimitive,
30 opDivide
33 class definition
35 public:
36 definition();
37 ~definition();
38 char *name;
39 char *def;
40 opType op;
41 definition *arg1;
42 definition *arg2;
43 int index;
46 definition::definition ()
48 name = def = NULL;
49 arg1 = arg2 = NULL;
52 definition::~definition ()
54 free (name);
55 free (def);
58 DerivedMetrics::DerivedMetrics ()
60 items = new Vector<definition*>;
63 DerivedMetrics::~DerivedMetrics ()
65 Destroy (items);
68 definition *
69 DerivedMetrics::add_definition (char *_name, char *_username, char *_def)
71 definition *p;
73 // if the name doesn't matter, maybe there is a duplicate we can use
74 if (_name == NULL)
76 int i;
77 Vec_loop (definition*, items, i, p)
79 if (strcmp (p->def, _def) == 0)
80 return p;
84 p = new definition;
85 p->name = dbe_strdup (_name);
86 p->def = dbe_strdup (_def);
88 // parse the definition
89 if (strchr (_def, '/') == NULL)
91 // it's a primitive metric
92 p->op = opPrimitive;
93 p->arg1 = p->arg2 = NULL;
96 else
98 // it's some operation on arguments
99 p->op = opDivide;
100 char *op_ptr = strchr (p->def, '/');
101 *op_ptr = 0;
102 p->arg1 = add_definition (NULL, NULL, p->def);
103 *op_ptr = '/';
104 p->arg2 = add_definition (NULL, NULL, op_ptr + 1);
106 p->index = items->size ();
107 items->append (p);
108 return p;
111 int *
112 DerivedMetrics::construct_map (Vector<Metric*> *mitems, BaseMetric::SubType st, char *expr_spec)
114 if (items == NULL)
115 return NULL;
116 int ndm = items->size ();
117 if (ndm == 0)
118 return NULL;
119 int nmetrics = mitems->size ();
121 // allocate arrays for the mapping between derived metrics and requested values
122 int *map = (int *) malloc (ndm * sizeof (int));
124 // map derived metrics to requested metrics // EUGENE explain this more clearly
125 // 0 means not mapped
126 // >0 means primitive metric maps to map-1
127 // <0 means derived metric maps to 1-map
128 int ndm_requested = 0;
129 for (int idm = 0; idm < ndm; idm++)
131 definition *defdm = items->fetch (idm);
132 map[idm] = 0;
134 // figure out what name to use for this derived metric
135 char *dname;
136 if (defdm->op == opPrimitive)
137 dname = defdm->def;
138 else
140 dname = defdm->name;
141 if (dname == NULL) break;
144 // look for this name among metrics
145 int im;
146 for (im = 0; im < nmetrics; im++)
148 Metric *m = mitems->fetch (im);
149 if (strcmp (dname, m->get_cmd ()) == 0 && m->get_subtype () == st)
150 // apparent match, but let's check comparison mode
151 if (dbe_strcmp (expr_spec, m->get_expr_spec ()) == 0)
152 break;
155 // encode the mapping
156 if (im >= nmetrics)
157 map[idm] = 0; // does not map to requested metrics
158 else if (defdm->op == opPrimitive)
159 map[idm] = +1 + im; // encode as a positive index
160 else
162 map[idm] = -1 - im; // encode as a negative index
163 ndm_requested++;
166 if (ndm_requested == 0)
168 free (map);
169 map = NULL;
171 return map;
174 void
175 DerivedMetrics::fill_dependencies (definition *def, int *vec)
177 switch (def->op)
179 case opPrimitive:
180 vec[def->index] = 1;
181 break;
182 case opDivide:
183 fill_dependencies (def->arg1, vec);
184 fill_dependencies (def->arg2, vec);
185 break;
186 default:
187 break;
191 Vector<definition*> *
192 DerivedMetrics::get_dependencies (definition *def)
194 int n = items->size ();
196 // zero out a vector representing definitions
197 int *vec = (int *) malloc (n * sizeof (int));
198 for (int i = 0; i < n; i++)
199 vec[i] = 0;
200 fill_dependencies (def, vec);
202 // construct the dependency vector
203 Vector<definition*> *dependencies = new Vector<definition*>;
204 for (int i = 0; i < n; i++)
205 if (vec[i] == 1)
206 dependencies->append (items->fetch (i));
207 free (vec);
208 return dependencies;
211 void
212 DerivedMetrics::dump (FILE *dis_file, int verbosity)
214 int i;
215 definition *item;
217 // deal with the possibility that names might be NULL
218 const char *UNNAMED = "(unnamed)";
219 #define NAME(x) ( (x) ? (x) : UNNAMED)
221 Vec_loop (definition*, items, i, item)
223 // at low verbosity, skip over some items
224 if (verbosity == 0)
226 if (item->name == NULL)
227 continue;
228 if (strcmp (item->name, item->def) && item->op == opPrimitive)
229 continue;
232 // dump the definition
233 switch (item->op)
235 case opPrimitive:
236 fprintf (dis_file, "%s [%s] is a primitive metric\n", NAME (item->name),
237 item->def);
238 break;
239 case opDivide:
240 fprintf (dis_file, "%s [%s] = %s [%s] / %s [%s]\n", NAME (item->name),
241 item->def, NAME (item->arg1->name), item->arg1->def,
242 NAME (item->arg2->name), item->arg2->def);
243 break;
244 default:
245 fprintf (dis_file, "%s [%s] has an unrecognized op %d\n",
246 NAME (item->name), item->def, item->op);
247 break;
252 double
253 DerivedMetrics::eval_one_item (definition *def, int *map, double *values)
255 switch (def->op)
257 case opNULL:
258 fprintf (stderr, GTXT ("cannot eval NULL expression\n"));
259 return 0.;
260 case opPrimitive:
262 int ival = map[def->index];
263 if (ival <= 0) return 0.;
264 ival--;
265 return values[ival];
267 case opDivide:
269 double x1 = eval_one_item (def->arg1, map, values);
270 double x2 = eval_one_item (def->arg2, map, values);
271 if (x2 == 0) return 0.;
272 return (x1 / x2);
274 default:
275 fprintf (stderr, GTXT ("unknown expression\n"));
276 return 0.;
281 DerivedMetrics::eval (int *map, double *values)
283 for (int i = 0, n = items->size (); i < n; i++)
285 if (map[i] < 0)
287 int ival = -1 - map[i];
288 values[ival] = eval_one_item (items->fetch (i), map, values);
291 return 0;