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

Popular posts from this blog

SPO600 Project Stage 1 (Pt.1) - Create a GCC Pass

SPO600 Project Stage 2 (Pt.1) - GCC pass locating clone function

SPO600 Project Stage 2 (Pt.2) - GCC pass locating clone function -modified version