Index: gcc/flags.h =================================================================== --- gcc/flags.h (revision 114563) +++ gcc/flags.h (working copy) @@ -194,6 +194,10 @@ extern int profile_flag; extern int profile_arc_flag; +/* Nonzero if generating code graph */ + +extern int flag_code_graph_generation; + /* Nonzero if value profile should be measured. */ extern int flag_profile_values; Index: gcc/cgraph.c =================================================================== --- gcc/cgraph.c (revision 114563) +++ gcc/cgraph.c (working copy) @@ -68,7 +68,8 @@ int cgraph_varpool_n_nodes; static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes; static struct cgraph_edge *create_edge (struct cgraph_node *, - struct cgraph_node *); + struct cgraph_node *, + location_t call_location); static hashval_t hash_node (const void *); static int eq_node (const void *, const void *); @@ -152,7 +153,7 @@ cgraph_node_for_identifier (tree id) /* Create edge from CALLER to CALLEE in the cgraph. */ static struct cgraph_edge * -create_edge (struct cgraph_node *caller, struct cgraph_node *callee) +create_edge (struct cgraph_node *caller, struct cgraph_node *callee, location_t call_location) { struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge)); struct cgraph_edge *edge2; @@ -180,6 +181,7 @@ create_edge (struct cgraph_node *caller, edge->caller = caller; edge->callee = callee; + edge->call_location = call_location; edge->next_caller = callee->callers; edge->next_callee = caller->callees; caller->callees = edge; @@ -295,7 +297,7 @@ cgraph_mark_needed_node (struct cgraph_n struct cgraph_edge * cgraph_record_call (tree caller, tree callee) { - return create_edge (cgraph_node (caller), cgraph_node (callee)); + return create_edge (cgraph_node (caller), cgraph_node (callee), input_location); } void Index: gcc/cgraph.h =================================================================== --- gcc/cgraph.h (revision 114563) +++ gcc/cgraph.h (working copy) @@ -126,6 +126,9 @@ struct cgraph_edge GTY(()) /* When NULL, inline this call. When non-NULL, points to the explanation why function was not inlined. */ const char *inline_failed; + + /* CodeViz: Location the call occurred at */ + location_t call_location; }; /* The cgraph_varpool data structure. Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 114563) +++ gcc/tree.h (working copy) @@ -3115,4 +3115,11 @@ typedef enum extern int tree_node_counts[]; extern int tree_node_sizes[]; +/* + * CodeViz functions to get the output file handle for cdepn files + */ +FILE *cdepn_open(char *filename); +void cdepn_close(void); +int cdepn_checkprint(void *fncheck); + #endif /* GCC_TREE_H */ Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 114563) +++ gcc/common.opt (working copy) @@ -456,6 +456,10 @@ fnon-call-exceptions Common Support synchronous non-call exceptions +fcode-graph-generation +Common +Enable code graph generation + fold-unroll-loops Common Perform loop unrolling when iteration count is known Index: gcc/toplev.c =================================================================== --- gcc/toplev.c (revision 114563) +++ gcc/toplev.c (working copy) @@ -950,6 +950,10 @@ int flag_renumber_insns = 1; /* If nonzero, use the graph coloring register allocator. */ int flag_new_regalloc = 0; +/* Nonzero if generating call graph. */ + +int flag_code_graph_generation = 0; + /* Nonzero if we perform superblock formation. */ int flag_tracer = 0; @@ -1149,6 +1153,7 @@ static const lang_independent_options f_ {"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1 }, {"signaling-nans", &flag_signaling_nans, 1 }, {"bounds-check", &flag_bounds_check, 1 }, + {"code-graph-generation", &flag_code_graph_generation, 1 }, {"single-precision-constant", &flag_single_precision_constant, 1 }, {"time-report", &time_report, 1 }, {"mem-report", &mem_report, 1 }, @@ -4675,6 +4680,58 @@ do_compile (void) timevar_print (stderr); } +/* + * codeviz: Open the cdepn file. This is called with a filename by main() + * and with just NULL for every other instance to return just the handle + */ +FILE *g_fnref_f = NULL; +char cdepnfile[256] = "--wonthappen--"; + +FILE *cdepn_open(char *filename) +{ + struct stat cdepnstat; + int errval; + time_t currtime; + if (filename && g_fnref_f == NULL) { + strcpy(cdepnfile, filename); + strcat(cdepnfile, ".cdepn"); + + /* + * Decide whether to open write or append. There appears to be a weird + * bug that decides to open the file twice, overwriting all the cdepn + * information put there before + */ + errval = stat(cdepnfile, &cdepnstat); + currtime = time(NULL); + if (errval == -1 || currtime - cdepnstat.st_mtime > 5) { + g_fnref_f = fopen(cdepnfile, "w"); + fprintf(stderr, "opened dep file %s\n",cdepnfile); + } + else { + g_fnref_f = fopen(cdepnfile, "a"); + fprintf(stderr, "append dep file %s\n",cdepnfile); + } + + fflush(stderr); + } + + return g_fnref_f; +} + +void cdepn_close(void) +{ + if (g_fnref_f) { + fclose(g_fnref_f); + } + g_fnref_f = NULL; +} + +int cdepn_checkprint(void *fncheck) +{ + return 1; + /*return (void *)fncheck == (void *)decl_name; */ +} + /* Entry point of cc1, cc1plus, jc1, f771, etc. Exit code is FATAL_EXIT_CODE if can't open files or if there were any errors, or SUCCESS_EXIT_CODE if compilation succeeded. @@ -4696,8 +4753,13 @@ toplev_main (unsigned int argc, const ch randomize (); /* Exit early if we can (e.g. -help). */ - if (!exit_after_options) + if (!exit_after_options) { + if (flag_code_graph_generation) + cdepn_open(main_input_filename); do_compile (); + if (flag_code_graph_generation) + cdepn_close(); + } if (errorcount || sorrycount) return (FATAL_EXIT_CODE); Index: gcc/cgraphunit.c =================================================================== --- gcc/cgraphunit.c (revision 114563) +++ gcc/cgraphunit.c (working copy) @@ -320,7 +320,10 @@ static void cgraph_analyze_function (struct cgraph_node *node) { tree decl = node->decl; + tree thisTree, calleeTree; + FILE *fnref_f; struct cgraph_edge *e; + struct cgraph_edge *calleeEdge; current_function_decl = decl; @@ -358,6 +361,35 @@ cgraph_analyze_function (struct cgraph_n node->analyzed = true; current_function_decl = NULL; + if (!flag_code_graph_generation) + goto rest_in_cgraph_analyze; + + /* CodeViz: Output information on this node */ + thisTree = node->decl; + if ((fnref_f = cdepn_open(NULL))) + { + fprintf(fnref_f,"F {%s} {%s:%d}\n", + lang_hooks.decl_printable_name (thisTree, 2), + DECL_SOURCE_FILE (thisTree), DECL_SOURCE_LINE (thisTree)); + } + + /* CodeViz: Output information on all functions this node calls */ + for (calleeEdge = node->callees; calleeEdge; calleeEdge = calleeEdge->next_callee) + { + calleeTree = calleeEdge->callee->decl; + if (thisTree != NULL && calleeTree != NULL && + (fnref_f = cdepn_open(NULL)) != NULL) { + fprintf(fnref_f, "C {%s} {%s:%d} {%s}\n", + lang_hooks.decl_printable_name (thisTree, 2), + calleeEdge->call_location.file, calleeEdge->call_location.line, + lang_hooks.decl_printable_name (calleeTree, 2)); + } + else { + printf("CODEVIZ: Unexpected NULL encountered\n"); + } + } + +rest_in_cgraph_analyze: /* Possibly warn about unused parameters. */ if (warn_unused_parameter) do_warn_unused_parameter (decl); Index: gcc/opts.c =================================================================== --- gcc/opts.c (revision 114563) +++ gcc/opts.c (working copy) @@ -1361,6 +1361,10 @@ common_handle_option (size_t scode, cons stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (arg)); break; + case OPT_fcode_graph_generation: + flag_code_graph_generation = value; + break; + case OPT_fstrength_reduce: flag_strength_reduce = value; break;