Mercurial > cospy
view src/cospy.c @ 8:5502f175d348
Show functions being called
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Wed, 08 Sep 2010 22:16:25 +0800 |
parents | 7fec19e27411 |
children | 958c2366e682 |
line wrap: on
line source
#include "gcc-plugin.h" #include "plugin-version.h" #include "system.h" #include "coretypes.h" #include "tree-pass.h" #include "tree.h" #include "gimple.h" #include "cgraph.h" #include <stdio.h> int plugin_is_GPL_compatible; /*! \brief Parse a tree of type and return respective string. * * \return a string for the type. It must be free through ggc_free(). */ static char * parse_type(tree type_node) { tree type_v; tree *pointers; tree type_decl, type_name; int lvl = 0; int const_cnt = 0; char *type_str; const char *base_type_name; int type_str_len; int i, ptr_i; /* Collect pointers */ type_v = type_node; while(TREE_CODE(type_v) == POINTER_TYPE) { if(TREE_READONLY(type_v)) const_cnt++; type_v = TREE_TYPE(type_v); lvl++; } pointers = (tree *)ggc_alloc(sizeof(tree) * lvl); type_v = type_node; for(ptr_i = 0; ptr_i < lvl; ptr_i++) { pointers[ptr_i] = type_v; type_v = TREE_TYPE(type_v); } /* Get name of base type */ type_decl = TYPE_NAME(type_v); type_name = DECL_NAME(type_decl); base_type_name = IDENTIFIER_POINTER(type_name); /* Compute total length of string of full type */ type_str_len = lvl + strlen(base_type_name) + const_cnt * 5; /* "const" */ if(TREE_READONLY(type_v)) type_str_len += 6; /* "const " */ type_str = (char *)ggc_alloc(type_str_len + 1); /* modify const for base type */ type_str[0] = 0; if(TREE_READONLY(type_v)) strcpy(type_str, "const "); strcat(type_str, base_type_name); /* Add pointers and const modifications after base type */ i = strlen(type_str); for(ptr_i = lvl - 1; ptr_i >= 0; ptr_i--) { type_v = pointers[ptr_i]; type_str[i++] = '*'; if(TREE_READONLY(type_v)) { type_str[i] = 0; strcat(type_str, "const"); i += 5; } } type_str[i] = 0; ggc_free(pointers); return type_str; } /*! \brief Show functions that called by a specified function. * * \param cgn is cgraph_node of a function. */ static void show_callees(struct cgraph_node *cgn) { struct cgraph_edge *edge; struct cgraph_node *callee_cgn; tree callee, callee_name; /* Follow edges to called functions */ edge = cgn->callees; while(edge) { callee_cgn = edge->callee; callee = callee_cgn->decl; callee_name = DECL_NAME(callee); printf(" call %s\n", IDENTIFIER_POINTER(callee_name)); edge = edge->next_callee; } } static void handle_all_passes(void *gcc_data, void *user_data) { tree decl; tree fntype; tree arg, arg_name; tree arg_type; struct cgraph_node *cgn; char *arg_type_str; function_args_iterator itr; decl = cfun->decl; cgn = cgraph_node(decl); printf("%s:%d:%s\n", current_function_name(), DECL_SOURCE_LINE(decl), DECL_SOURCE_FILE(decl)); show_callees(cgn); arg = DECL_ARGUMENTS(decl); while(arg) { arg_name = DECL_NAME(arg); arg_type = TREE_TYPE(arg); arg_type_str = parse_type(arg_type); printf(" %s:%s\n", IDENTIFIER_POINTER(arg_name), arg_type_str); ggc_free(arg_type_str); arg = TREE_CHAIN(arg); } } int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) { struct cgraph_node_hook_list *hook; if (!plugin_default_version_check (version, &gcc_version)) return 1; printf("Initialize plugin %s\n", plugin_info->base_name); register_callback(plugin_info->base_name, PLUGIN_ALL_PASSES_START, handle_all_passes, NULL); return 0; }