Project Stage 1: Create a Basic GCC Pass

After performed Lab4, at this stage we create a pass for the current development version of the GCC compiler which:
  • Iterates through the code being compiled;
  • Prints the name of every function being compiled;
  • Prints a count of the number of basic blocks in each function; and
  • Prints a count of the number of gimple statements in each function.
Step 1: Prepare Environment

I already have ~/SomeLocalDir: GCC source code directory
                       ~/gcc-build-001: GCC build directory (where I ran configure).
                       ~/gcc-test-001:Installation directory




Step 2: Create a New GCC Pass
Go to the GCC source directory: cd ~/SomeLocalDir/gcc
Create my-pass.cc file: nano hxu_pass.cc

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "tree-pass.h"
#include "cgraph.h"
#include "function.h"
#include "basic-block.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "cfg.h"

namespace {

const pass_data hxu_pass_data = {
    GIMPLE_PASS,          // Type of pass
    "hxu_pass",           // Name of pass
    OPTGROUP_NONE,        // No optimization group
    TV_NONE,              // No timevar
    PROP_cfg,             // Properties required
    0,                    // Properties provided
    0,                    // Properties destroyed
    0,                    // todo_flags_start
    0                     // todo_flags_finish
};

// Pass class definition
class hxu_pass : public gimple_opt_pass {
public:
    hxu_pass(gcc::context *ctxt) : gimple_opt_pass(hxu_pass_data, ctxt) {}

    unsigned int execute(function *fun) override {
        int bb_cnt = 0, gimple_stmt_cnt = 0;
        basic_block bb;

        // Iterate over basic blocks
        FOR_ALL_BB_FN(bb, fun) {
            bb_cnt++;
            // Iterate over GIMPLE statements in each basic block
            for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
                gimple_stmt_cnt++;
            }
        }

        // Output to dump file (if enabled)
        if (dump_file) {
            fprintf(dump_file, "=== Function '%s' ===\n", function_name(fun));
            fprintf(dump_file, "  Number of Basic Blocks: %d\n", bb_cnt);
            fprintf(dump_file, "  Number of GIMPLE statements: %d\n\n", gimple_stmt_cnt);
        }

        return 0;
    }
};

} // end anonymous namespace

// Factory method to create the pass
gimple_opt_pass *make_pass_hxu(gcc::context *ctxt) {
    return new hxu_pass(ctxt);
}

Step 3: Include New Pass in passes.def

The passes.def file contains all the macros needed to manage GCC passes. We now need to insert our hxu_pass in this file so that GCC knows when to invoke it during compilation.

Since early passes handle parsing and gimplification, and later passes handle final transformations and code generation, we will place our hxu_pass late in the optimization pipeline, so we can analyze code after most optimizations are done.

find pass.def


add my pass:






Step 4: Include New Pass in tree-pass.h

Once I added NEXT_PASS to passes.def,
I also need to declare the make_hxu_pass function in tree-pass.h.






Step 5: Update the Build System (Makefile.in)

To make sure hxu_pass.cc gets compiled, Ineed to add it to Makefile.in.

nano Makefile.in
then search OBJS = \ AND add my pass:








Step 6: Rebuild GCC

ran following commends:

cd ~/gcc-build-001
rm Makefile
~/SomeLocalDir/configure --prefix=$HOME/gcc-test-001
time make -j 20 |& tee rebuild.log





Step 7: Testing Pass






Execute test command:
./xgcc -B./ -g -O0 -fno-builtin -fdump-tree-hxu_pass -o hello hello.c

then view the generated dump file:














Here I can see the basic block and gimple statistics output by my pass!

Result on X86-001:










Although the overall goal of this project is clear, it was difficult for me to fully understand the specific meaning and process at first. Especially as a beginner in GCC internals, it took time to grasp how GIMPLE passes work and how to properly register them in the compiler pipeline. In addition, troubleshooting errors during the integration process was quite challenging, since GCC's build system and pass registration are complex. This project stage1 helps understand and extend GCC’s compilation pipeline by adding a custom analysis phase, which can be a foundation for more advanced optimizations.







Comments

Popular posts from this blog

(lab1)6502 Assembly Language Lab

(Lab4) GCC Build Lab

(lab2)6502 Math Lab