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

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 pt.1, I was trying to modify the code to locate the clone but in vain.

I sought advice from my professor, Chris Tyler and note that for the default version of the clone, the node->name() function will return function name without any .variant, i.e. without .default . That's why the previous version does not work. As a result, I revised the code accordingly and it works now.

revised 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 *)
{
    struct cgraph_node *node;
    std::map<std::string, cgraph_node*> variant_map;

    int counter = 0;
    struct cgraph_node *variant1_node = nullptr;
    struct cgraph_node *variant2_node = nullptr;
    std::string base_function;

    FOR_EACH_FUNCTION (node)
    {
        if (!dump_file)
            continue;

        const char *fname = node->name();
        std::string name(fname);

        if (name.find(".resolver") != std::string::npos)
            continue;

        size_t dot_pos = name.find(".");
        std::string base;
        if (dot_pos == std::string::npos)
                base = name;
        else{
                base = name.substr(0, dot_pos);
        }
f (variant_map.find(base) != variant_map.end())
        {
            variant1_node = variant_map[base];
            variant2_node = node;
            base_function = base;
            fprintf(dump_file, "---------------------------clone found for function '%s'---------------\n",base.c_str());
            fprintf(dump_file, "  Variant 1: %s\n", variant1_node->name());
            fprintf(dump_file, "  Variant 2: %s\n", variant2_node->name());
            break;
        }
        else
        {
            variant_map[base] = node;

        }

        function *fun = node->get_fun();
        if (!fun)
        {
            continue;
        }
    }
    return 0;
  }

} // anon namespace

gimple_opt_pass *
make_pass_jeff (gcc::context *ctxt)
{
  return new pass_jeff (ctxt);
}

It can locate the clone now. However, since the execute run the once for every function and I used FOR_EACH_FUNCTION inside the execute, it turns out run n*n time in total when there are n functions. I would like to remove the duplicate works so I re-wrote it again.

This is the modified version.


/* 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;
 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_node = nullptr;
        struct cgraph_node *variant2_node = 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())
        {
            variant1_node = variant_map[base];
            variant2_node = node;
            base_function = base;
            fprintf(dump_file, "---------------------------clone found for function '%s'---------------\n",base.c_str());
            fprintf(dump_file, "  Variant 1: %s\n", variant1_node->name());
            fprintf(dump_file, "  Variant 2: %s\n", variant2_node->name());
 return 0;
        }
        else
        {
            variant_map[base] = node;
            return 0;
        }

        function *fun = node->get_fun();
        if (!fun)
        {
            return 0;
        }
        return 0;
  }

} // anon namespace

gimple_opt_pass *
make_pass_jeff (gcc::context *ctxt)
{
  return new pass_jeff (ctxt);
}


Now the output can correctly show the clone located.


In part 3, I will modify the code to compare two clone functions.


 

 

Comments

Popular posts from this blog

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

SPO600 Project Stage 3 - Identify clones of multiple functions and compare them

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