X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gprof%2Fcg_dfn.c;h=5c8b5ec745e2f46a30bc3f5e8cb9acfde52ea1c5;hb=38fafa6d088439f82e140d2f60f76fa0d15def57;hp=f93a9d882b01bc3241b74ff0242f2fdf25b8cc73;hpb=5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7;p=deliverable%2Fbinutils-gdb.git diff --git a/gprof/cg_dfn.c b/gprof/cg_dfn.c index f93a9d882b..5c8b5ec745 100644 --- a/gprof/cg_dfn.c +++ b/gprof/cg_dfn.c @@ -1,61 +1,85 @@ /* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that: (1) source distributions retain this entire copyright - * notice and comment, and (2) distributions including binaries display - * the following acknowledgement: ``This product includes software - * developed by the University of California, Berkeley and its contributors'' - * in the documentation or other materials provided with the distribution - * and in all advertising materials mentioning features or use of this - * software. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#include +#include "libiberty.h" #include "gprof.h" +#include "search_list.h" +#include "source.h" +#include "symtab.h" #include "cg_arcs.h" #include "cg_dfn.h" -#include "symtab.h" #include "utils.h" -#define DFN_DEPTH 100 +#define DFN_INCR_DEPTH (128) -typedef struct { +typedef struct + { Sym *sym; int cycle_top; -} DFN_Stack; + } +DFN_Stack; -DFN_Stack dfn_stack[DFN_DEPTH]; -int dfn_depth = 0; -int dfn_counter = DFN_NAN; +static bfd_boolean is_numbered PARAMS ((Sym *)); +static bfd_boolean is_busy PARAMS ((Sym *)); +static void find_cycle PARAMS ((Sym *)); +static void pre_visit PARAMS ((Sym *)); +static void post_visit PARAMS ((Sym *)); + +DFN_Stack *dfn_stack = NULL; +int dfn_maxdepth = 0; +int dfn_depth = 0; +int dfn_counter = DFN_NAN; /* * Is CHILD already numbered? */ -static bool -DEFUN(is_numbered, (child), Sym *child) +static bfd_boolean +is_numbered (child) + Sym *child; { - return child->cg.top_order != DFN_NAN && child->cg.top_order != DFN_BUSY; -} /* is_numbered */ + return child->cg.top_order != DFN_NAN && child->cg.top_order != DFN_BUSY; +} /* * Is CHILD already busy? */ -static bool -DEFUN(is_busy, (child), Sym *child) +static bfd_boolean +is_busy (child) + Sym *child; { - if (child->cg.top_order == DFN_NAN) { - return FALSE; - } /* if */ - return TRUE; -} /* is_busy */ + if (child->cg.top_order == DFN_NAN) + { + return FALSE; + } + return TRUE; +} /* @@ -65,92 +89,123 @@ DEFUN(is_busy, (child), Sym *child) * depth-first number). */ static void -DEFUN(find_cycle, (child), Sym *child) +find_cycle (child) + Sym *child; { - Sym *head = 0; - Sym *tail; - int cycle_top; - int index; - - for (cycle_top = dfn_depth; cycle_top > 0; --cycle_top) { - head = dfn_stack[cycle_top].sym; - if (child == head) { - break; - } /* if */ - if (child->cg.cyc.head != child && child->cg.cyc.head == head) { - break; - } /* if */ - } /* for */ - if (cycle_top <= 0) { - fprintf(stderr, "[find_cycle] couldn't find head of cycle\n"); - done(1); - } /* if */ - DBG(DFNDEBUG, printf("[find_cycle] dfn_depth %d cycle_top %d ", - dfn_depth, cycle_top); - if (head) { - print_name(head); - } else { - printf(""); - } /* if */ - printf("\n")); - if (cycle_top == dfn_depth) { - /* - * This is previous function, e.g. this calls itself. Sort of - * boring. - * - * Since we are taking out self-cycles elsewhere no need for - * the special case, here. - */ - DBG(DFNDEBUG, - printf("[find_cycle] "); print_name(child); printf("\n")); - } else { - /* - * Glom intervening functions that aren't already glommed into - * this cycle. Things have been glommed when their cyclehead - * field points to the head of the cycle they are glommed - * into. - */ - for (tail = head; tail->cg.cyc.next; tail = tail->cg.cyc.next) { - /* void: chase down to tail of things already glommed */ - DBG(DFNDEBUG, - printf("[find_cycle] tail "); print_name(tail); printf("\n")); - } /* for */ - /* - * If what we think is the top of the cycle has a cyclehead - * field, then it's not really the head of the cycle, which is - * really what we want. - */ - if (head->cg.cyc.head != head) { - head = head->cg.cyc.head; - DBG(DFNDEBUG, printf("[find_cycle] new cyclehead "); - print_name(head); printf("\n")); - } /* if */ - for (index = cycle_top + 1; index <= dfn_depth; ++index) { - child = dfn_stack[index].sym; - if (child->cg.cyc.head == child) { - /* - * Not yet glommed anywhere, glom it and fix any - * children it has glommed. - */ - tail->cg.cyc.next = child; - child->cg.cyc.head = head; - DBG(DFNDEBUG, printf("[find_cycle] glomming "); - print_name(child); printf(" onto "); print_name(head); - printf("\n")); - for (tail = child; tail->cg.cyc.next; tail = tail->cg.cyc.next) + Sym *head = 0; + Sym *tail; + int cycle_top; + int index; + + for (cycle_top = dfn_depth; cycle_top > 0; --cycle_top) + { + head = dfn_stack[cycle_top].sym; + if (child == head) + { + break; + } + if (child->cg.cyc.head != child && child->cg.cyc.head == head) + { + break; + } + } + if (cycle_top <= 0) + { + fprintf (stderr, "[find_cycle] couldn't find head of cycle\n"); + done (1); + } +#ifdef DEBUG + if (debug_level & DFNDEBUG) + { + printf ("[find_cycle] dfn_depth %d cycle_top %d ", + dfn_depth, cycle_top); + if (head) + { + print_name (head); + } + else + { + printf (""); + } + printf ("\n"); + } +#endif + if (cycle_top == dfn_depth) + { + /* + * This is previous function, e.g. this calls itself. Sort of + * boring. + * + * Since we are taking out self-cycles elsewhere no need for + * the special case, here. + */ + DBG (DFNDEBUG, + printf ("[find_cycle] "); + print_name (child); + printf ("\n")); + } + else + { + /* + * Glom intervening functions that aren't already glommed into + * this cycle. Things have been glommed when their cyclehead + * field points to the head of the cycle they are glommed + * into. + */ + for (tail = head; tail->cg.cyc.next; tail = tail->cg.cyc.next) + { + /* void: chase down to tail of things already glommed */ + DBG (DFNDEBUG, + printf ("[find_cycle] tail "); + print_name (tail); + printf ("\n")); + } + /* + * If what we think is the top of the cycle has a cyclehead + * field, then it's not really the head of the cycle, which is + * really what we want. + */ + if (head->cg.cyc.head != head) + { + head = head->cg.cyc.head; + DBG (DFNDEBUG, printf ("[find_cycle] new cyclehead "); + print_name (head); + printf ("\n")); + } + for (index = cycle_top + 1; index <= dfn_depth; ++index) + { + child = dfn_stack[index].sym; + if (child->cg.cyc.head == child) + { + /* + * Not yet glommed anywhere, glom it and fix any + * children it has glommed. + */ + tail->cg.cyc.next = child; + child->cg.cyc.head = head; + DBG (DFNDEBUG, printf ("[find_cycle] glomming "); + print_name (child); + printf (" onto "); + print_name (head); + printf ("\n")); + for (tail = child; tail->cg.cyc.next; tail = tail->cg.cyc.next) { - tail->cg.cyc.next->cg.cyc.head = head; - DBG(DFNDEBUG, printf("[find_cycle] and its tail "); - print_name(tail->cg.cyc.next); printf(" onto "); - print_name(head); printf("\n")); - } /* for */ - } else if (child->cg.cyc.head != head /* firewall */) { - fprintf(stderr, "[find_cycle] glommed, but not to head\n"); - done(1); - } /* if */ - } /* for */ - } /* if */ -} /* find_cycle */ + tail->cg.cyc.next->cg.cyc.head = head; + DBG (DFNDEBUG, printf ("[find_cycle] and its tail "); + print_name (tail->cg.cyc.next); + printf (" onto "); + print_name (head); + printf ("\n")); + } + } + else if (child->cg.cyc.head != head /* firewall */ ) + { + fprintf (stderr, "[find_cycle] glommed, but not to head\n"); + done (1); + } + } + } +} /* @@ -158,19 +213,24 @@ DEFUN(find_cycle, (child), Sym *child) * the stack and mark it busy. */ static void -DEFUN(pre_visit, (parent), Sym *parent) +pre_visit (parent) + Sym *parent; { - ++dfn_depth; - if (dfn_depth >= DFN_DEPTH) { - fprintf(stderr, "[pre_visit] dfn_stack overflow\n"); - done(1); - } /* if */ - dfn_stack[dfn_depth].sym = parent; - dfn_stack[dfn_depth].cycle_top = dfn_depth; - parent->cg.top_order = DFN_BUSY; - DBG(DFNDEBUG, printf("[pre_visit]\t\t%d:", dfn_depth); print_name(parent); - printf("\n")); -} /* pre_visit */ + ++dfn_depth; + + if (dfn_depth >= dfn_maxdepth) + { + dfn_maxdepth += DFN_INCR_DEPTH; + dfn_stack = xrealloc (dfn_stack, dfn_maxdepth * sizeof *dfn_stack); + } + + dfn_stack[dfn_depth].sym = parent; + dfn_stack[dfn_depth].cycle_top = dfn_depth; + parent->cg.top_order = DFN_BUSY; + DBG (DFNDEBUG, printf ("[pre_visit]\t\t%d:", dfn_depth); + print_name (parent); + printf ("\n")); +} /* @@ -178,61 +238,71 @@ DEFUN(pre_visit, (parent), Sym *parent) * and number functions if PARENT is head of a cycle. */ static void -DEFUN(post_visit, (parent), Sym *parent) +post_visit (parent) + Sym *parent; { - Sym *member; - - DBG(DFNDEBUG, printf("[post_visit]\t%d: ", dfn_depth); - print_name(parent); printf("\n")); - /* - * Number functions and things in their cycles unless the function - * is itself part of a cycle: - */ - if (parent->cg.cyc.head == parent) { - ++dfn_counter; - for (member = parent; member; member = member->cg.cyc.next) { - member->cg.top_order = dfn_counter; - DBG(DFNDEBUG, printf("[post_visit]\t\tmember "); - print_name(member); - printf("-> cg.top_order = %d\n", dfn_counter)); - } /* for */ - } else { - DBG(DFNDEBUG, printf("[post_visit]\t\tis part of a cycle\n")); - } /* if */ - --dfn_depth; -} /* post_visit */ + Sym *member; + + DBG (DFNDEBUG, printf ("[post_visit]\t%d: ", dfn_depth); + print_name (parent); + printf ("\n")); + /* + * Number functions and things in their cycles unless the function + * is itself part of a cycle: + */ + if (parent->cg.cyc.head == parent) + { + ++dfn_counter; + for (member = parent; member; member = member->cg.cyc.next) + { + member->cg.top_order = dfn_counter; + DBG (DFNDEBUG, printf ("[post_visit]\t\tmember "); + print_name (member); + printf ("-> cg.top_order = %d\n", dfn_counter)); + } + } + else + { + DBG (DFNDEBUG, printf ("[post_visit]\t\tis part of a cycle\n")); + } + --dfn_depth; +} /* * Given this PARENT, depth first number its children. */ void -DEFUN(cg_dfn, (parent), Sym *parent) +cg_dfn (parent) + Sym *parent; { - Arc *arc; - - DBG(DFNDEBUG, printf("[dfn] dfn( "); print_name(parent); printf(")\n")); - /* - * If we're already numbered, no need to look any further: - */ - if (is_numbered(parent)) { - return; - } /* if */ - /* - * If we're already busy, must be a cycle: - */ - if (is_busy(parent)) { - find_cycle(parent); - return; - } /* if */ - pre_visit(parent); - /* - * Recursively visit children: - */ - for (arc = parent->cg.children; arc; arc = arc->next_child) { - cg_dfn(arc->child); - } /* for */ - post_visit(parent); -} /* cg_dfn */ - - /*** end of cg_dfn.c ***/ + Arc *arc; + + DBG (DFNDEBUG, printf ("[dfn] dfn( "); + print_name (parent); + printf (")\n")); + /* + * If we're already numbered, no need to look any further: + */ + if (is_numbered (parent)) + { + return; + } + /* + * If we're already busy, must be a cycle: + */ + if (is_busy (parent)) + { + find_cycle (parent); + return; + } + pre_visit (parent); + /* + * Recursively visit children: + */ + for (arc = parent->cg.children; arc; arc = arc->next_child) + { + cg_dfn (arc->child); + } + post_visit (parent); +}