SPO600 Project Stage 2 (Pt.3) - GCC pass comparing two clone functions
In project stage 1, I created a GCC pass in both x86-64 server and AARCH64 server to print the functions' name and counting number of block. In stage 2 pt2, I successfully locate the clones.
Mission: compare the number of block number and number of gimple statement.
Trial 1:
Now, I am trying to modified the code to compare the block number and statement number.
Modified code:
/* Test Pass Jeff Yau, Seneca Polytechnic College Student ID :142466234 Modelled on tree-nrv.cc and tree-ctyler.cc by Chris Tyler, Seneca Polytechnic College, 2024-11 This file is part of GCC. GCC 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 3, or (at your option) any later version. GCC 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 GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ #include <map> #include <string> #include <stdlib.h> #include "config.h" #include "system.h" #include "coretypes.h" #include "backend.h" #include "tree.h" #include "gimple.h" #include "tree-pass.h" #include "ssa.h" #include "tree-pretty-print.h" #include "gimple-iterator.h" #include "gimple-walk.h" #include "internal-fn.h" #include "gimple-pretty-print.h" #include "cgraph.h" #include "gimple-ssa.h" #include "attribs.h" #include "pretty-print.h" #include "tree-inline.h" #include "intl.h" #include "function.h" #include "basic-block.h" namespace { const pass_data pass_data_jeff = { GIMPLE_PASS, /* type */ "jeff", /* name */ OPTGROUP_NONE, /* optinfo_flags */ TV_NONE, /* tv_id */ PROP_cfg, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ 0, /* todo_flags_finish */ }; class pass_jeff : public gimple_opt_pass { public: pass_jeff (gcc::context *ctxt) : gimple_opt_pass (pass_data_jeff, ctxt) {} /* opt_pass methods: */ bool gate (function *) final override { return 1; } unsigned int execute (function *) final override; }; // class pass_jeff unsigned int pass_jeff::execute (function * func) { static std::map<std::string, cgraph_node*> variant_map; struct cgraph_node *node = cgraph_node::get(func->decl); struct cgraph_node *variant1 = nullptr; struct cgraph_node *variant2 = nullptr; std::string base_function; if (!dump_file) return 0; const char *fname = node->name(); std::string name(fname); if (name.find(".resolver") != std::string::npos) return 0; size_t dot_pos = name.find("."); std::string base; if (dot_pos == std::string::npos) base = name; else{ base = name.substr(0, dot_pos); } if (variant_map.find(base) == variant_map.end()) { variant_map[base] = node; return 0; } variant1 = variant_map[base]; variant2 = node; base_function = base; fprintf(dump_file, "---------------------------clone found for function '%s'---------------\n",base.c_str()); fprintf(dump_file, " Variant 1: %s\n", variant1->name() ); fprintf(dump_file, " Variant 2: %s\n", variant2->name() ); if (!variant1) { return 0; } int block_counter = 0; int gimple_sta_counter = 0; basic_block bb; function *fn1 = DECL_STRUCT_FUNCTION(variant1->decl); FOR_EACH_BB_FN(bb,fn1){ block_counter++; for (gimple_stmt_iterator it = gsi_start_bb (bb); !gsi_end_p (it); gsi_next (&it)){ gimple_sta_counter++; } } fprintf(dump_file,"block_counter: %d, gimple_counter: %d\n",block_counter, gimple_sta_counter); FOR_EACH_BB_FN(bb,func){ block_counter--; for (gimple_stmt_iterator it = gsi_start_bb (bb); !gsi_end_p (it); gsi_next (&it)){ gimple_sta_counter--; } } fprintf(dump_file,"block_counter: %d, gimple_counter: %d\n",block_counter, gimple_sta_counter); if (block_counter || gimple_sta_counter){ fprintf(dump_file, "NOPRUNE: %s\n", base_function.c_str()); return 0; } fprintf(dump_file, "PRUNE: %s\n", base_function.c_str()); return 0; } } // anon namespace gimple_opt_pass * make_pass_jeff (gcc::context *ctxt) { return new pass_jeff (ctxt); }
Segmentation fault occur.
clone-test-core.c:28:6: internal compiler error: Segmentation fault
After studying the result, I noted that "function *fn1 = DECL_STRUCT_FUNCTION(variant1->decl)" cant really return the expected function to us.
Trial 2:
I modified the code. I tried to use the below instruction the get the function* with a cgraph_node*. I also tried to use FOR_EACH_FUNCTION_WITH_GIMPLE_BODY additionally to ensure the node pointer is working. But, never able the get a working function pointer.
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(var1_node){
function* variant1_function = var1_node->get_fun();
function* variant1_function = DECL_STRUCT_FUNCTION(variant1->decl);
I decided to re-write the entire program. See Pt.4.
Comments
Post a Comment