For this project we are going to make custom GCC pass for our GCC compiler that we done in Lab 4. The requirements simply follows:
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.
Before we start anything lets go ahead and recap the file structures with ll command
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree-pass.h"
#include "pass_manager.h"
#include "context.h"
#include "diagnostic-core.h"
#include "tree.h"
#include "tree-core.h"
#include "basic-block.h"
#include "gimple.h"
#include "gimple-iterator.h"
namespace {
// Define pass metadata
const pass_data sj_pass_data = {
GIMPLE_PASS, // Pass type
"tree-sj-pass", // Pass name
OPTGROUP_NONE, // No optimization group
TV_TREE_OPS, // Timevar
0, 0, 0, 0 // Default settings
};
// Custom GIMPLE pass class
class sj_pass : public gimple_opt_pass {
public:
// Constructor
sj_pass(gcc::context *ctxt) : gimple_opt_pass(sj_pass_data, ctxt) {}
// Gate function - always true
bool gate(function *fun) override {
return fun != nullptr;
}
// Main execution function
unsigned int execute(function *fun) override {
fprintf(stderr, "Processing function: %s\n", function_name(fun));
int basic_block_count = 0, gimple_stmt_count = 0;
// Iterate over basic blocks
basic_block bb;
FOR_EACH_BB_FN(bb, fun) {
if (!bb) continue; // Safety check
basic_block_count++;
// Iterate over GIMPLE statements
for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
gimple_stmt_count++;
}
}
// Print results
fprintf(stderr, "Number of basic blocks: %d\nNumber of GIMPLE statements: %d\n",
basic_block_count, gimple_stmt_count);
return 0;
}
};
}
// Factory function to create an instance of the pass
gimple_opt_pass *make_tree_sj_pass(gcc::context *ctxt) {
return new sj_pass(ctxt);
}
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree-pass.h"
#include "pass_manager.h"
#include "context.h"
#include "diagnostic-core.h"
#include "tree.h"
#include "tree-core.h"
#include "basic-block.h"
#include "gimple.h"
#include "gimple-iterator.h"
namespace {
// Define pass metadata
const pass_data tree_sj_pass_data = {
GIMPLE_PASS, // Pass type
"tree-sj", // Pass name
OPTGROUP_NONE, // No optimization group
TV_TREE_OPS, // Timevar
0, 0, 0, 0 // Default settings
};
// Custom GIMPLE pass class
class tree_sj_pass : public gimple_opt_pass {
public:
// Constructor
tree_sj_pass(gcc::context *ctxt) : gimple_opt_pass(tree_sj_pass_data, ctxt) {}
// Gate function - always true
bool gate(function *fun) override {
return fun != nullptr;
}
// Main execution function
unsigned int execute(function *fun) override {
fprintf(stderr, "[tree-sj] Processing function: %s\n", function_name(fun));
int basic_block_count = 0;
int gimple_stmt_count = 0;
basic_block bb;
// Iterate over basic blocks
FOR_EACH_BB_FN(bb, fun) {
if (!bb) continue; // Safety check
basic_block_count++;
// Iterate over GIMPLE statements
for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
gimple_stmt_count++;
}
}
// Print results
fprintf(stderr, "[tree-sj] Basic Blocks: %d | GIMPLE Statements: %d\n",
basic_block_count, gimple_stmt_count);
return 0;
}
};
} // namespace
extern gimple_opt_pass *make_pass_harden_control_flow_redundancy (gcc::context
*ctxt);
extern gimple_opt_pass *make_pass_sj(gcc::context *ctxt);
and edit passes.def to ensure pass is running during compilation
tree-complex.o \
tree-data-ref.o \
tree-sj.o \
tree-dfa.o \
tree-diagnostic.o \
tree-diagnostic-client-data-hooks.o \
tree-dump.o \
and edit passes.def to ensure pass is running during compilation

then if you run the build command again you will see its getting built
few things to remember while debugging :
- naming convention syntaxes are of course important, double check, doublecheck
NEXT_PASS (pass_asan_O0);
NEXT_PASS (pass_tsan_O0);
NEXT_PASS (pass_sanopt);
NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_musttail);
NEXT_PASS (pass_lower_resx);
NEXT_PASS (pass_sj);
NEXT_PASS (pass_nrv);
NEXT_PASS (pass_gimple_isel);
NEXT_PASS (pass_harden_conditiona
slee569@x86-001:~/gcc-test-001$ /home/slee569/gcc-build-001/gcc/xgcc -B/home/slee569/gcc-build-001/gcc/ test.c -o test_c.out
./test_c.out
[tree-sj] Processing function: main
[tree-sj] Basic Blocks: 2 | GIMPLE Statements: 5
Hello from GCC!
PASS running test file here! hows it going!
and got the expected result that is running with my customized GCC pass.
This project was really really time consuming if you start to mess up some little details like typos... dont be like me and make sure whatever you write is consistent and keep think about the connection between .def .h makefile and your basic gcc pass. Also again make sure to edit the files in right place, i tried a lot of times with wrong placement(out of scope, linkage issue, ggc not finding certain things that i implemented, sometimes even suspecting xgcc might be corrupted but it turned out that i was the one who made mistakes on editing files..) i think its all coming from what we edited so make sure its in right lines.
------------------------------------------------
Summary:
🔴 Configuration Issues: Cache and environment inconsistencies made it hard to get a clean build.
🔴 Pass Registration Errors: Undefined references and missing make_pass_sj()
function led to failed builds.
🔴 GCC Compilation Complexity: Minor changes could break the build, requiring a lot of debugging.
✅ Successful Build: Despite errors, we eventually got a working customized GCC!
✅ Custom Pass Execution: tree-sj
executed and provided basic block & GIMPLE statistics.
✅ Improved Debugging Skills: Learned to analyze config.log
, build.log
, and compiler errors efficiently.
Final Takeaway:
This project was a hands-on journey into compiler design, teaching us how GCC compiles, optimizes, and executes code. We overcame tough debugging challenges and built a working custom pass, reinforcing our understanding of compiler internals and optimization techniques.
No comments:
Post a Comment