Wolfgang Thallergcc16 merge934c3885 months agoHistory
293 lines · 6.5 KB · C++
RawDownload
/* Copyright (C) 2021-2026 Free Software Foundation, Inc.   Contributed by Oracle.    This file is part of GNU Binutils.    This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3, or (at your option)   any later version.    This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.    You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, 51 Franklin Street - Fifth Floor, Boston,   MA 02110-1301, USA.  */ #include "config.h"#include <strings.h>#include "DerivedMetrics.h"#include "util.h" enum opType{  opNULL,  opPrimitive,  opDivide}; class definition{public:  definition();  ~definition();  char *name;  char *def;  opType op;  definition *arg1;  definition *arg2;  int index;}; definition::definition (){  name = def = NULL;  arg1 = arg2 = NULL;} definition::~definition (){  free (name);  free (def);} DerivedMetrics::DerivedMetrics (){  items = new Vector<definition*>;} DerivedMetrics::~DerivedMetrics (){  Destroy (items);} definition *DerivedMetrics::add_definition (char *_name, char *_username, char *_def){  definition *p;   // if the name doesn't matter, maybe there is a duplicate we can use  if (_name == NULL)    {      int i;      Vec_loop (definition*, items, i, p)      {	if (strcmp (p->def, _def) == 0)	  return p;      }    }   p = new definition;  p->name = dbe_strdup (_name);  p->def = dbe_strdup (_def);   // parse the definition  if (strchr (_def, '/') == NULL)    {      // it's a primitive metric      p->op = opPrimitive;      p->arg1 = p->arg2 = NULL;     }  else    {      // it's some operation on arguments      p->op = opDivide;      char *op_ptr = strchr (p->def, '/');      *op_ptr = 0;      p->arg1 = add_definition (NULL, NULL, p->def);      *op_ptr = '/';      p->arg2 = add_definition (NULL, NULL, op_ptr + 1);    }  p->index = items->size ();  items->append (p);  return p;} int *DerivedMetrics::construct_map (Vector<Metric*> *mitems, BaseMetric::SubType st, char *expr_spec){  if (items == NULL)    return NULL;  int ndm = items->size ();  if (ndm == 0)    return NULL;  int nmetrics = mitems->size ();   // allocate arrays for the mapping between derived metrics and requested values  int *map = (int *) xmalloc (ndm * sizeof (int));   // map derived metrics to requested metrics    // EUGENE explain this more clearly  //   0  means not mapped  //  >0  means primitive metric maps to map-1  //  <0  means  derived  metric maps to 1-map  int ndm_requested = 0;  for (int idm = 0; idm < ndm; idm++)    {      definition *defdm = items->fetch (idm);      map[idm] = 0;       // figure out what name to use for this derived metric      char *dname;      if (defdm->op == opPrimitive)	dname = defdm->def;      else	{	  dname = defdm->name;	  if (dname == NULL) break;	}       // look for this name among metrics      int im;      for (im = 0; im < nmetrics; im++)	{	  Metric *m = mitems->fetch (im);	  if (strcmp (dname, m->get_cmd ()) == 0 && m->get_subtype () == st)	    // apparent match, but let's check comparison mode	    if (dbe_strcmp (expr_spec, m->get_expr_spec ()) == 0)	      break;	}       // encode the mapping      if (im >= nmetrics)	map[idm] = 0; // does not map to requested metrics      else if (defdm->op == opPrimitive)	map[idm] = +1 + im; // encode as a positive index      else	{	  map[idm] = -1 - im; // encode as a negative index	  ndm_requested++;	}    }  if (ndm_requested == 0)    {      free (map);      map = NULL;    }  return map;} voidDerivedMetrics::fill_dependencies (definition *def, int *vec){  switch (def->op)    {    case opPrimitive:      vec[def->index] = 1;      break;    case opDivide:      fill_dependencies (def->arg1, vec);      fill_dependencies (def->arg2, vec);      break;    default:      break;    }} Vector<definition*> *DerivedMetrics::get_dependencies (definition *def){  int n = items->size ();   // zero out a vector representing definitions  int *vec = (int *) xmalloc (n * sizeof (int));  for (int i = 0; i < n; i++)    vec[i] = 0;  fill_dependencies (def, vec);   // construct the dependency vector  Vector<definition*> *dependencies = new Vector<definition*>;  for (int i = 0; i < n; i++)    if (vec[i] == 1)      dependencies->append (items->fetch (i));  free (vec);  return dependencies;} voidDerivedMetrics::dump (FILE *dis_file, int verbosity){  int i;  definition *item;   // deal with the possibility that names might be NULL  const char *UNNAMED = "(unnamed)";#define NAME(x) ( (x) ? (x) : UNNAMED)   Vec_loop (definition*, items, i, item)  {    // at low verbosity, skip over some items    if (verbosity == 0)      {	if (item->name == NULL)	  continue;	if (strcmp (item->name, item->def) && item->op == opPrimitive)	  continue;      }     // dump the definition    switch (item->op)      {      case opPrimitive:	fprintf (dis_file, "%s [%s] is a primitive metric\n", NAME (item->name),		 item->def);	break;      case opDivide:	fprintf (dis_file, "%s [%s] = %s [%s] / %s [%s]\n", NAME (item->name),		 item->def, NAME (item->arg1->name), item->arg1->def,		 NAME (item->arg2->name), item->arg2->def);	break;      default:	fprintf (dis_file, "%s [%s] has an unrecognized op %d\n",		 NAME (item->name), item->def, item->op);	break;      }  }} doubleDerivedMetrics::eval_one_item (definition *def, int *map, double *values){  switch (def->op)    {    case opNULL:      fprintf (stderr, GTXT ("cannot eval NULL expression\n"));      return 0.;    case opPrimitive:      {	int ival = map[def->index];	if (ival <= 0) return 0.;	ival--;	return values[ival];      }    case opDivide:      {	double x1 = eval_one_item (def->arg1, map, values);	double x2 = eval_one_item (def->arg2, map, values);	if (x2 == 0) return 0.;	return (x1 / x2);      }    default:      fprintf (stderr, GTXT ("unknown expression\n"));      return 0.;    }} intDerivedMetrics::eval (int *map, double *values){  for (int i = 0, n = items->size (); i < n; i++)    {      if (map[i] < 0)	{	  int ival = -1 - map[i];	  values[ival] = eval_one_item (items->fetch (i), map, values);	}    }  return 0;} 

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t