Mercurial > cospy
view src/cospy.c @ 9:958c2366e682
More information about design and consideration
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Thu, 09 Sep 2010 08:20:15 +0800 |
parents | 5502f175d348 |
children | ecc20b5a4942 |
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> /* This is required for GCC plugin, or it is can not be loaded */ int plugin_is_GPL_compatible; /*! \brief Parse a tree of type and return respective string. * * The struncture of a pointer type * - pointer:pointer_type * - type:*_type * - name:type_decl * - name:identifier * * For a constant type, it is flaged as a readonly. * * \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 ptr_lvl = 0; int const_cnt = 0; char *type_str; const char *base_type_name; int type_str_len; int str_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); ptr_lvl++; } pointers = (tree *)ggc_alloc(sizeof(tree) * ptr_lvl); type_v = type_node; for(ptr_i = 0; ptr_i < ptr_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 = ptr_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); /* base type and constant modification */ 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 */ str_i = strlen(type_str); for(ptr_i = ptr_lvl - 1; ptr_i >= 0; ptr_i--) { type_v = pointers[ptr_i]; type_str[str_i++] = '*'; if(TREE_READONLY(type_v)) { strcpy(type_str + str_i, "const"); str_i += 5; } } type_str[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; } } /*! \brief This function is called before running all_passes. * * all_passes is a list of optimization passes of GCC. See * init_optimization_passes() in gcc/passes.c of GCC. * * This function is called for every function. */ 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; /* * GCC uses cgraph_node to save information of functions and * relationships between functions (a.k.a call graphy). */ 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); /* * Parse and show arguments of the function. */ arg = DECL_ARGUMENTS(decl); while(arg) { /* * The structure of an argument. * - parm * - name:identifier * - type:type * - name:type_decl * - name:identifier */ 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); } } /*! \brief Initialize function for the plugin. */ 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 a callback called before running passes in all_passes. */ register_callback(plugin_info->base_name, PLUGIN_ALL_PASSES_START, handle_all_passes, NULL); return 0; }