Project Stage 1 - Creating GCC Pass
Project Stage 1
Creating GCC Pass and Building GCC
gcc gcc-build-001 gcc-test-001 password.txt spo600
STEP 2: I changed directory to ~/gcc/gcc to create my "tree-count-pass.cc". My gcc pass analyzes the compiled program by iterating through functions, counting their basic blocks and GIMPLE statements, and logging this data for debugging and analysis. Although this code can be improved to be functional, this has displayed logic that could be useful for a dummy pass. Down below is the code for my pass:
#include "gcc-plugin.h"
#include "plugin-version.h"
#include "pass_manager.h"
#include "tree-pass.h"
#include "context.h"
#include "diagnostic.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "basic-block.h"
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "context.h"
int plugin_is_GPL_compatible;
namespace {
const pass_data count_pass_data = {
GIMPLE_PASS,
"count_pass",
OPTGROUP_NONE,
TV_NONE,
PROP_gimple_any,
0,
0,
0,
};
class count_pass : public simple_ipa_opt_pass {
public:
count_pass(gcc::context *ctxt) : simple_ipa_opt_pass(count_pass_data, ctxt) {}
bool gate(function *fun) override {
return true;
}
unsigned int execute(function *fun) override {
if (dump_file) {
fprintf(dump_file, "\nAnalyzing function: %s\n", function_name(fun));
int basic_block_count = 0;
int gimple_stmt_count = 0;
basic_block bb;
FOR_EACH_BB_FN(bb, fun) {
basic_block_count++;
for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
gimple_stmt_count++;
}
}
fprintf(dump_file, "Basic Blocks: %d\n", basic_block_count);
fprintf(dump_file, "GIMPLE Statements: %d\n", gimple_stmt_count);
}
return 0;
}
};
}
extern "C" {
gcc::context *global_context;
static struct plugin_info count_plugin_info = {
.version = "1.0",
.help = "Counts functions, basic blocks, and GIMPLE statements."
};
int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) {
if (!plugin_default_version_check(version, &gcc_version)) {
error_at (UNKNOWN_LOCATION, "GCC version mismatch");
return 1;
}
register_pass_info pass_info;
pass_info.pass = new count_pass(global_context);
pass_info.reference_pass_name = "gimple";
pass_info.ref_pass_instance_number = 1;
pass_info.pos_op = PASS_POS_INSERT_AFTER;
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, nullptr, &pass_info);
register_callback(plugin_info->base_name, PLUGIN_INFO, nullptr, &count_plugin_info);
return 0;
}
extern "C" gimple_opt_pass *make_pass_count(gcc::context *ctxt) {
return new count_pass(ctxt);
}
}
STEP 3: Ensuring make_pass_count is recognized by inserting a line of code in tree-pass.h. Since I had added a line of code extern gimple_opt_pass *make_pass_count(gcc:: *);, I also needed to update passes.def by adding this line NEXT_PASS(make_pass_count); - by doing so, I registered make_pass_count as a pass.
NOTE: I had to create an instance of my pass to properly link into GCC's pass manager by having function added in tree-count-pass.
extern "C" gimple_opt_pass *make_pass_count(gcc::context *ctxt) {
return new count_pass(ctxt);
}
Comments
Post a Comment