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