// Insert code for incrementing our byte, flop, etc. counters. bool BytesFlops::runOnFunction(Function& function) { // Do nothing if we're supposed to ignore this function. StringRef function_name = function.getName(); string function_name_orig = demangle_func_name(function_name.str()); remove_all_instances(function_name_orig, ' '); // Normalize the name by removing spaces. if ( instrument_only != NULL ) { if ( (instrument_only->find(function_name) == instrument_only->end()) && (instrument_only->find(function_name_orig) == instrument_only->end()) ) return false; } if ( dont_instrument != NULL ) { if ( (dont_instrument->find(function_name) != dont_instrument->end()) || (dont_instrument->find(function_name_orig) != dont_instrument->end()) ) return false; } if (function_name == "bf_categorize_counters") // Avoid the endless recursion that would be caused if we were // to instrument bf_categorize_counters() using // bf_categorize_counters(). return false; if ( "bf_initialize_func_map" == function_name ) { return false; } if ( function.empty() ) { return false; } // Reset all of our static counters. static_loads = 0; static_stores = 0; static_flops = 0; static_ops = 0; static_cond_brs = 0; static_bblocks = 0; // Instrument "interesting" instructions in every basic block. Module* module = function.getParent(); instrument_entire_function(module, function, function_name); // Return, indicating that we modified this function. return true; }
// Read a list of function names, one per line, from a file into a // set. C++ function names can be either mangled or unmangled. static void functions_from_file(string filename, set<string>* funcset) { ifstream infile(filename.c_str(), ifstream::in); if (!infile.good()) report_fatal_error(StringRef("Failed to open file ") + filename); string oneline; while (infile.good() && getline(infile, oneline)) { // Normalize unmangled names by removing spaces then insert the // result into the set. remove_all_instances(oneline, ' '); funcset->insert(oneline); } infile.close(); }
// Parse a list of function names into a set. The trick is that (1) // demangled C++ function names are split (at commas) across list // elements and need to be recombined, and (2) the form "@filename" // causes function names to be read from a file. set<string>* parse_function_names(vector<string>& funclist) { if (funclist.size() == 0) return NULL; string funcname; size_t lparens = 0; size_t rparens = 0; set<string>* resulting_set = new(set<string>); for (vector<string>::iterator fniter = funclist.begin(); fniter != funclist.end(); fniter++) { // Combine pieces of mangled names. string partial_name(*fniter); if (lparens > 0 || rparens > 0) funcname += ','; funcname += partial_name; lparens += tally_all_instances(partial_name, '('); rparens += tally_all_instances(partial_name, ')'); if (lparens != rparens) continue; // We have a complete function name. Add it to the set. if (funcname[0] == '@') // Read function names from a file into the set. functions_from_file(funcname.substr(1), resulting_set); else { // Function name was specified literally. Normalize // unmangled names by removing spaces then insert the result // into the set. remove_all_instances(funcname, ' '); resulting_set->insert(funcname); } funcname = ""; lparens = 0; rparens = 0; } return resulting_set; }