cg_print.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,268 行 · 第 1/3 页
C
1,268 行
/* cg_print.c - Print routines for displaying call graphs. Copyright 2000, 2001 Free Software Foundation, Inc. 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 2 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "libiberty.h"#include "cg_arcs.h"#include "cg_print.h"#include "hist.h"#include "utils.h"/* Return value of comparison functions used to sort tables. */#define LESSTHAN -1#define EQUALTO 0#define GREATERTHAN 1static void order_and_dump_functions_by_arcs PARAMS ((Arc **, unsigned long, int, Arc **, unsigned long *));/* Declarations of automatically generated functions to output blurbs. */extern void bsd_callg_blurb PARAMS ((FILE * fp));extern void fsf_callg_blurb PARAMS ((FILE * fp));double print_time = 0.0;static voidDEFUN_VOID (print_header){ if (first_output) first_output = FALSE; else printf ("\f\n"); if (!bsd_style_output) { if (print_descriptions) printf (_("\t\t Call graph (explanation follows)\n\n")); else printf (_("\t\t\tCall graph\n\n")); } printf (_("\ngranularity: each sample hit covers %ld byte(s)"), (long) hist_scale * sizeof (UNIT)); if (print_time > 0.0) printf (_(" for %.2f%% of %.2f seconds\n\n"), 100.0 / print_time, print_time / hz); else { printf (_(" no time propagated\n\n")); /* This doesn't hurt, since all the numerators will be 0.0. */ print_time = 1.0; } if (bsd_style_output) { printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", "", "", "", "", _("called"), _("total"), _("parents")); printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", _("index"), _("%time"), _("self"), _("descendents"), _("called"), _("self"), _("name"), _("index")); printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", "", "", "", "", _("called"), _("total"), _("children")); printf ("\n"); } else { printf (_("index %% time self children called name\n")); }}/* Print a cycle header. */static voidDEFUN (print_cycle, (cyc), Sym * cyc){ char buf[BUFSIZ]; sprintf (buf, "[%d]", cyc->cg.index); printf (bsd_style_output ? "%-6.6s %5.1f %7.2f %11.2f %7lu" : "%-6.6s %5.1f %7.2f %7.2f %7lu", buf, 100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time, cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls); if (cyc->cg.self_calls != 0) printf ("+%-7lu", cyc->cg.self_calls); else printf (" %7.7s", ""); printf (_(" <cycle %d as a whole> [%d]\n"), cyc->cg.cyc.num, cyc->cg.index);}/* Compare LEFT and RIGHT membmer. Major comparison key is CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS. */static intDEFUN (cmp_member, (left, right), Sym * left AND Sym * right){ double left_time = left->cg.prop.self + left->cg.prop.child; double right_time = right->cg.prop.self + right->cg.prop.child; unsigned long left_calls = left->ncalls + left->cg.self_calls; unsigned long right_calls = right->ncalls + right->cg.self_calls; if (left_time > right_time) return GREATERTHAN; if (left_time < right_time) return LESSTHAN; if (left_calls > right_calls) return GREATERTHAN; if (left_calls < right_calls) return LESSTHAN; return EQUALTO;}/* Sort members of a cycle. */static voidDEFUN (sort_members, (cyc), Sym * cyc){ Sym *todo, *doing, *prev; /* Detach cycle members from cyclehead, and insertion sort them back on. */ todo = cyc->cg.cyc.next; cyc->cg.cyc.next = 0; for (doing = todo; doing && doing->cg.cyc.next; doing = todo) { todo = doing->cg.cyc.next; for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next) { if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN) break; } doing->cg.cyc.next = prev->cg.cyc.next; prev->cg.cyc.next = doing; }}/* Print the members of a cycle. */static voidDEFUN (print_members, (cyc), Sym * cyc){ Sym *member; sort_members (cyc); for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next) { printf (bsd_style_output ? "%6.6s %5.5s %7.2f %11.2f %7lu" : "%6.6s %5.5s %7.2f %7.2f %7lu", "", "", member->cg.prop.self / hz, member->cg.prop.child / hz, member->ncalls); if (member->cg.self_calls != 0) printf ("+%-7lu", member->cg.self_calls); else printf (" %7.7s", ""); printf (" "); print_name (member); printf ("\n"); }}/* Compare two arcs to/from the same child/parent. - if one arc is a self arc, it's least. - if one arc is within a cycle, it's less than. - if both arcs are within a cycle, compare arc counts. - if neither arc is within a cycle, compare with time + child_time as major key arc count as minor key. */static intDEFUN (cmp_arc, (left, right), Arc * left AND Arc * right){ Sym *left_parent = left->parent; Sym *left_child = left->child; Sym *right_parent = right->parent; Sym *right_child = right->child; double left_time, right_time; DBG (TIMEDEBUG, printf ("[cmp_arc] "); print_name (left_parent); printf (" calls "); print_name (left_child); printf (" %f + %f %lu/%lu\n", left->time, left->child_time, left->count, left_child->ncalls); printf ("[cmp_arc] "); print_name (right_parent); printf (" calls "); print_name (right_child); printf (" %f + %f %lu/%lu\n", right->time, right->child_time, right->count, right_child->ncalls); printf ("\n"); ); if (left_parent == left_child) return LESSTHAN; /* Left is a self call. */ if (right_parent == right_child) return GREATERTHAN; /* Right is a self call. */ if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0 && left_parent->cg.cyc.num == left_child->cg.cyc.num) { /* Left is a call within a cycle. */ if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0 && right_parent->cg.cyc.num == right_child->cg.cyc.num) { /* Right is a call within the cycle, too. */ if (left->count < right->count) return LESSTHAN; if (left->count > right->count) return GREATERTHAN; return EQUALTO; } else { /* Right isn't a call within the cycle. */ return LESSTHAN; } } else { /* Left isn't a call within a cycle. */ if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0 && right_parent->cg.cyc.num == right_child->cg.cyc.num) { /* Right is a call within a cycle. */ return GREATERTHAN; } else { /* Neither is a call within a cycle. */ left_time = left->time + left->child_time; right_time = right->time + right->child_time; if (left_time < right_time) return LESSTHAN; if (left_time > right_time) return GREATERTHAN; if (left->count < right->count) return LESSTHAN; if (left->count > right->count) return GREATERTHAN; return EQUALTO; } }}static voidDEFUN (sort_parents, (child), Sym * child){ Arc *arc, *detached, sorted, *prev; /* Unlink parents from child, then insertion sort back on to sorted's parents. *arc the arc you have detached and are inserting. *detached the rest of the arcs to be sorted. sorted arc list onto which you insertion sort. *prev arc before the arc you are comparing. */ sorted.next_parent = 0; for (arc = child->cg.parents; arc; arc = detached) { detached = arc->next_parent; /* Consider *arc as disconnected; insert it into sorted. */ for (prev = &sorted; prev->next_parent; prev = prev->next_parent) { if (cmp_arc (arc, prev->next_parent) != GREATERTHAN) break; } arc->next_parent = prev->next_parent; prev->next_parent = arc; } /* Reattach sorted arcs to child. */ child->cg.parents = sorted.next_parent;}static voidDEFUN (print_parents, (child), Sym * child){ Sym *parent; Arc *arc; Sym *cycle_head; if (child->cg.cyc.head != 0) cycle_head = child->cg.cyc.head; else cycle_head = child; if (!child->cg.parents) { printf (bsd_style_output ? _("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n") : _("%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n"), "", "", "", "", "", ""); return; } sort_parents (child); for (arc = child->cg.parents; arc; arc = arc->next_parent) { parent = arc->parent; if (child == parent || (child->cg.cyc.num != 0 && parent->cg.cyc.num == child->cg.cyc.num)) { /* Selfcall or call among siblings. */ printf (bsd_style_output ? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s " : "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ", "", "", "", "", arc->count, ""); print_name (parent); printf ("\n"); } else { /* Regular parent of child. */ printf (bsd_style_output ? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu " : "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ", "", "", arc->time / hz, arc->child_time / hz, arc->count, cycle_head->ncalls); print_name (parent); printf ("\n"); } }}static voidDEFUN (sort_children, (parent), Sym * parent){ Arc *arc, *detached, sorted, *prev; /* Unlink children from parent, then insertion sort back on to sorted's children. *arc the arc you have detached and are inserting. *detached the rest of the arcs to be sorted. sorted arc list onto which you insertion sort. *prev arc before the arc you are comparing. */ sorted.next_child = 0; for (arc = parent->cg.children; arc; arc = detached) { detached = arc->next_child; /* Consider *arc as disconnected; insert it into sorted. */ for (prev = &sorted; prev->next_child; prev = prev->next_child) { if (cmp_arc (arc, prev->next_child) != LESSTHAN) break; } arc->next_child = prev->next_child; prev->next_child = arc; } /* Reattach sorted children to parent. */ parent->cg.children = sorted.next_child;}static voidDEFUN (print_children, (parent), Sym * parent){ Sym *child; Arc *arc; sort_children (parent); arc = parent->cg.children; for (arc = parent->cg.children; arc; arc = arc->next_child) { child = arc->child; if (child == parent || (child->cg.cyc.num != 0 && child->cg.cyc.num == parent->cg.cyc.num)) { /* Self call or call to sibling. */ printf (bsd_style_output
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?