1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
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)
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. */
23 #include "DerivedMetrics.h"
46 definition::definition ()
52 definition::~definition ()
58 DerivedMetrics::DerivedMetrics ()
60 items
= new Vector
<definition
*>;
63 DerivedMetrics::~DerivedMetrics ()
69 DerivedMetrics::add_definition (char *_name
, char *_username
, char *_def
)
73 // if the name doesn't matter, maybe there is a duplicate we can use
77 Vec_loop (definition
*, items
, i
, p
)
79 if (strcmp (p
->def
, _def
) == 0)
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
93 p
->arg1
= p
->arg2
= NULL
;
98 // it's some operation on arguments
100 char *op_ptr
= strchr (p
->def
, '/');
102 p
->arg1
= add_definition (NULL
, NULL
, p
->def
);
104 p
->arg2
= add_definition (NULL
, NULL
, op_ptr
+ 1);
106 p
->index
= items
->size ();
112 DerivedMetrics::construct_map (Vector
<Metric
*> *mitems
, BaseMetric::SubType st
, char *expr_spec
)
116 int ndm
= items
->size ();
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
);
134 // figure out what name to use for this derived metric
136 if (defdm
->op
== opPrimitive
)
141 if (dname
== NULL
) break;
144 // look for this name among metrics
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)
155 // encode the mapping
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
162 map
[idm
] = -1 - im
; // encode as a negative index
166 if (ndm_requested
== 0)
175 DerivedMetrics::fill_dependencies (definition
*def
, int *vec
)
183 fill_dependencies (def
->arg1
, vec
);
184 fill_dependencies (def
->arg2
, vec
);
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
++)
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
++)
206 dependencies
->append (items
->fetch (i
));
212 DerivedMetrics::dump (FILE *dis_file
, int verbosity
)
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
226 if (item
->name
== NULL
)
228 if (strcmp (item
->name
, item
->def
) && item
->op
== opPrimitive
)
232 // dump the definition
236 fprintf (dis_file
, "%s [%s] is a primitive metric\n", NAME (item
->name
),
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
);
245 fprintf (dis_file
, "%s [%s] has an unrecognized op %d\n",
246 NAME (item
->name
), item
->def
, item
->op
);
253 DerivedMetrics::eval_one_item (definition
*def
, int *map
, double *values
)
258 fprintf (stderr
, GTXT ("cannot eval NULL expression\n"));
262 int ival
= map
[def
->index
];
263 if (ival
<= 0) return 0.;
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.;
275 fprintf (stderr
, GTXT ("unknown expression\n"));
281 DerivedMetrics::eval (int *map
, double *values
)
283 for (int i
= 0, n
= items
->size (); i
< n
; i
++)
287 int ival
= -1 - map
[i
];
288 values
[ival
] = eval_one_item (items
->fetch (i
), map
, values
);