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

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. Now, I would like to revise the pass again and increase it's functionality.

Step 1. Modify the pass

First, I would like to detect if the function is a clone. When a clone is detected, loop will be broken. Meanwhile, just ignore the count of statement and blocks first. They will be useful for later part.

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"

//added headers
#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(".");
           if (dot_pos == std::string::npos)
            continue;

        std::string base = name.substr(0, dot_pos);
        fprintf(dump_file, "--------------base is '%s'---------------\n",base.c_str());
        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());
            break;
        }
        else
        {
            variant_map[base] = node;
            fprintf(dump_file, "added function '%s' to dictionary\n",node->name());

        }
        fprintf(dump_file, "Function %d's Name is '%s'\n", ++counter, fname);

        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);
}
      


Step 2. make and install

Re-make the file and install the gcc with commands:
 time make -j 24 |& tee build.log
make install

No error after install.



Step 3. get the test case provided by professor

cd ~/spo600/spo600/lab4/testcases/
tar -xvzf /public/spo600-test-clone.tgz

Step 4. Revise the Makefile

revised the Makefile. change gcc to $(CC)

Step 5. compile with the gcc with the pass created

cd ~/spo600/spo600/lab4/testcases/spo600/examples/test-clone
make CC=/home/jyau11/spo600/lab4/gcc-test-003/bin/gcc  DUMP_ALL=1

 /home/jyau11/spo600/lab4/gcc-test-003/bin/gcc -O2 -fdump-tree-jeff clone-test-core.c -o test-clone

 cat clone-test-x86-prune-clone-test-core.c.265t.jeff

Unfortunately, there is no output showing any clone function.đŸ˜”

Step 6. Move the pass in passes.def to a later part

modify passes.def, then remove the entire build and test folder. re-make the build and install again

Step 7. compile the test-clone with the new gcc again


Unfortunately, the output show that the program is still unable to locate the clone function

To be continued.....


Comments

Popular posts from this blog

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

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