Project Stage 2: Custom Implementation

For this stage of the project I had to implement my own custom GCC pass to iterate through the code in the program that was being compiled. Below is my code.

#include "config.h"

#include "system.h"

#include "coretypes.h"

#include "tree.h"

#include "tree-pass.h"

#include "context.h"

#include "function.h"

#include "basic-block.h"  

#include "cfg.h"          

#include "gimple.h"      

#include "gimple-iterator.h"

#include "gimple-pretty-print.h"


namespace {

    const pass_data pass_data_ctyler = {

        GIMPLE_PASS,       // Type

        "ctyler",          // Name

        OPTGROUP_NONE,     // Option group

        TV_NONE,           // TV identifier

        PROP_cfg,          // Properties required

        0,                 // Properties provided

        0,                 // Properties destroyed

        0,                 // To-do flags start

        0                  // To-do flags finish

    };


    class pass_ctyler : public gimple_opt_pass {

    public:

        pass_ctyler(gcc::context *ctxt) : gimple_opt_pass(pass_data_ctyler, ctxt) {}


        // Always execute the pass

        bool gate(function *) override { return true; }


        // Main logic for the pass

        unsigned int execute(function *fun) override {

            basic_block bb;


            // Iterate over all basic blocks

            FOR_EACH_BB_FN(bb, fun) {

                gimple_stmt_iterator gsi;


                // Iterate over all statements in the basic block

                for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {

                    gimple *stmt = gsi_stmt(gsi);

                    if (dump_file) {

                        print_gimple_stmt(dump_file, stmt, 0, TDF_SLIM);

                    }

                }

            }


            // Emit a diagnostic message

            if (dump_file) {

                fprintf(dump_file, "PRUNE: %s\n", IDENTIFIER_POINTER(DECL_NAME(fun->decl)));

            }


            return 0;

        }

    };


} // End anonymous namespace


// Factory function to create the pass

gimple_opt_pass *make_pass_ctyler(gcc::context *ctxt) {

    return new pass_ctyler(ctxt);

}

I modified the sample pass that was provided to us by our professor and tried to implement my own code to iterate through the code, log gimple statements, and output a diagnostic prune: function_name message.

My code in comparison to the sample one is provides more simple information than the professors and simply tracks functions and their GIMPLE statements. 

 const pass_data pass_data_ctyler = {

        GIMPLE_PASS,       // Type

        "ctyler",          // Name

        OPTGROUP_NONE,     // Option group

        TV_NONE,           // TV identifier

        PROP_cfg,          // Properties required

        0,                 // Properties provided

        0,                 // Properties destroyed

        0,                 // To-do flags start

        0                  // To-do flags finish

    };

The initial part of my code is similar and just provides metadata for GCC about the pass itself. The main changes I made to the program were within the main logic of the code.

        unsigned int execute(function *fun) override {

            basic_block bb;


            // Iterate over all basic blocks

            FOR_EACH_BB_FN(bb, fun) {

                gimple_stmt_iterator gsi;


                // Iterate over all statements in the basic block

                for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {

                    gimple *stmt = gsi_stmt(gsi);

                    if (dump_file) {

                        print_gimple_stmt(dump_file, stmt, 0, TDF_SLIM);

                    }

                }

            }


            // Emit a diagnostic message

            if (dump_file) {

                fprintf(dump_file, "PRUNE: %s\n", IDENTIFIER_POINTER(DECL_NAME(fun->decl)));

            }


            return 0;

        }

My version of the pass uses TDF_SLIM when calling print_gimple_stmt which will generate a different output than TDF_VOPS like the sample code. This version just focuses on a minimal representation of the statements. My version also outputs PRUNE: function_name for every function that has been processed, this diagnostic doesn't actually perform pruning but is a step towards the right direction.
My version the pass is a simplified version of the one provided by the professor, but does not implement the cloning or pruning logic as outlined. I tried my best to implement these functions but due to time restriction and difficulties I was unable to complete it. 

Comments

Popular posts from this blog

Early stages of project

Building GCC again on aarch64-002

Project Stage 2: Testing