PROJECT STAGE 1- Part 2
Hello everyone! If you've been following, you would know that my Project Stage 1 did not go as smoothly as planned. In this blog, I'll walk you through how I investigated the issues and my debugging process. I had a big chunk of compiler errors but I am going to highlight the ones that stood out to me all throughout the process of getting my custom pass to successfully integrate into compiler. Thank you for your patience and let's get into it!
Error #1: Missing Declarations
I had errors that occurred from missing headers. Because of this encounter, I then realized how crucial it is to include the correct headers to ensure they declare the types, functions, macros and constants my file needs to successfully compile.
The following are my missing headers and why they are needed:
- gimple-iterator.h: This declares the types and functions used to iterate gimple statements. My pass uses this to count the number of gimple statements used in a basic block.
- tree-pass.h: This helps declare the pass_data structure which hold gimple_opt_pass which was where my pass was derived from.
- basic-block.h: This helped me use the FOR_EACH_BB_FN() which was essential to iterate over all the basic blocks in a function.
- function.h: This gave me access to a function's attributes such as function_name() which was used to print the function's name.
Error #2: Undefined Reference to the Factory Function
I got an error that says "undefined reference to gcc::make_count_pass(gcc::context*)". This means my factory function could be missing or placed in a wrong namespace. My fix was to place it within a namespace by doing this:
namespace gcc {
opt_pass *make_count_pass(gcc::context *ctxt) {
return new count_pass(ctxt);
}
}
Although this resolved the error temporarily, it caused another error, specifically a linking error. I discovered this during linking when the build system needed it globally, still stating that my factory function was not found. To permanently fix this error, my factory function had to be visible in a global namespace for it to pass.
Error #3: NEXT_PASS Macro Registration Issues
During the process, I encountered two NEXT_PASS() errors including NEXT_PASS requiring two arguments, and incorrect number for the second argument. The following are the errors produced:
- error: ‘NEXT_PASS’ requires 2 arguments, but only 1 given
- error: ‘count_pass_0’ was not declared in this scope; did you mean ‘count_pass_1’?
I fixed the first error inserting NEXT_PASS(count_pass, 0) and NEXT_PASS(count_pass, 1) into passes.def to supply the required number of arguments. This temporary fix may have satisfied the required arguments but then resulted in this next error which was caused by 'count_pass_0'. This error was due to it not being declared in the scope or was leading to a reference to a nonexistent instance and fortunately, a recommendation to insert a single NEXT_PASS() function that uses 1 as the second argument was produced which helped me fix the error overall.
Error #4: Missing Initializer for a pass_data Member
I encountered an error for todo_flag_finish which was a pass_data member, as stated in one of my compiler errors, "error: missing initializer for member ‘pass_data::todo_flags_finish’ [-Werror=missing-field-initializers]" was caused by a missing initializer. At first I only initialized three members by putting 0,0,0 but as soon as I realized this, I included another 0 at the end to ensure todo_flags_finish was initialized. Down below was my final fix for this error:
const pass_data count_pass_data = {
GIMPLE_PASS,
"count",
OPTGROUP_NONE,
TV_NONE,
PROP_gimple_any,
0, 0, 0, 0
};
Error #5: Incorrect Factory Function Name
Throughout the process, I realize that I have been using an incorrect factory function name that causes it to be invisible which eventually resulted in linker errors. To resolve this issue, I ensured that i used the correct factory function name to ensure the compiler links correctly.
Pass Successful!
After all the debugging, my custom pass was successfully integrated into the compiler. Before rebuilding GCC, I ran make clean to remove all generated files and started from scratch, which allowed everything to be rebuilt properly.
- I created a Hello.c file which contained basic code to run and test my pass
- Saved my hello file in the working directory
- I compiled my test file in my newly built GCC in the directory $HOME/gcc-test-001/bin/gcc
- Enabled my dump output by including this: -fdump-tree-count
Down below is a screenshot of me testing my pass:
FINAL CODE:
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "basic-block.h"
#include "function.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "tree-pass.h"
#include "context.h"
namespace {
const pass_data count_pass_data = {
GIMPLE_PASS,
"count",
OPTGROUP_NONE,
TV_NONE,
PROP_gimple_any,
0, 0, 0, 0
};
class count_pass : public gimple_opt_pass {
public:
count_pass(gcc::context *ctxt)
: gimple_opt_pass(count_pass_data, ctxt) {}
bool gate(function *fun) override {
(void) fun;
return true;
}
unsigned int execute(function *fun) override {
int bb_count = 0, gimple_count = 0;
basic_block bb;
FOR_EACH_BB_FN(bb, fun) {
for (gimple_stmt_iterator gsi = gsi_start_bb(bb);
!gsi_end_p(gsi);
gsi_next(&gsi)) {
gimple_count++;
}
bb_count++;
}
fprintf(stderr, "Function %s: %d BBs, %d GIMPLE stmts\n",
function_name(fun), bb_count, gimple_count);
}
return 0;
}
};
opt_pass *make_count_pass(gcc::context *ctxt) {
return new count_pass(ctxt);
}
REFLECTION:
This stage of the project took a considerable amount of time to complete, but after all the learnings and finally achieving a successful compilation made it worthwhile. Throughout this process, I learned a lot of invaluable knowledge especially the importance of understanding proper relationships between files, factory functions, expanding macros and many others that deepened my knowledge in this aspect. Although I recognize there is still much to learn, this experience has been a crucial stepping stone in my development, helping me prepare for the more challenging tasks relating to compiler optimization. I am now excited to explore and learn more from the next stage of this project.
Comments
Post a Comment