SPO600 2025 Winter Project - Stage 2: Updating tree-skim.cc and Verifying Dump File Output (part2)
To begin Stage 2 of my project, I started by updating my tree-skim.cc file to support scanning all functions in the compiled file. Here’s a summary of what I changed and how I tested it.
Original Version of tree-skim.cc
Initially, my execute() method only analyzed one function at a time and printed the number of basic blocks and GIMPLE statements per function. It didn’t iterate over all functions in the file.
Updated Version of tree-skim.cc
To scan all functions, I made the following updates:
• Added #include "cgraph.h" to access the function graph
• Used FOR_EACH_FUNCTION(node) inside the execute() method to list all functions in the program
• Printed the function names to the dump_file for output
#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"
#include "cgraph.h"
namespace {
// Define pass metadata
const pass_data pass_data_skim = {
GIMPLE_PASS, /* type */
"skim", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0, /* todo_flags_finish */
};
// Custom GIMPLE pass class
class pass_skim : public gimple_opt_pass {
public:
pass_skim(gcc::context *ctxt)
: gimple_opt_pass(pass_data_skim, ctxt) {}
bool gate(function *fun) final override {
return fun != nullptr;
}
unsigned int execute(function *fun) final override;
};
// Execute function implementation
unsigned int pass_skim::execute(function *fun) {
const char* fname = function_name(fun);
// Print current function info (just like before)
printf("Function: %s\n", fname);
int bb_count = 0;
int gimple_stmt_count = 0;
// Count BBs and GIMPLE statements for this function
basic_block bb;
FOR_EACH_BB_FN(bb, fun) {
if (!bb) continue;
bb_count++;
int bb_gimple_count = 0;
for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
bb_gimple_count++;
}
gimple_stmt_count += bb_gimple_count;
}
printf("Basic blocks: %d\n", bb_count);
printf("GIMPLE statements: %d\n\n", gimple_stmt_count);
// Now scan ALL functions (Step 1)
if (dump_file) {
fprintf(dump_file, "=== Scanning all functions ===\n");
struct cgraph_node *node;
FOR_EACH_FUNCTION(node) {
const char *fn_name = IDENTIFIER_POINTER(DECL_NAME(node->decl));
fprintf(dump_file, "Function found: %s\n", fn_name);
}
fprintf(dump_file, "=== End of function scan ===\n\n");
}
return 0;
}
} // namespace
// Register pass
gimple_opt_pass *make_pass_skim(gcc::context *ctxt) {
return new pass_skim(ctxt);
}
Building the Pass
After updating the code, I recompiled the project from my build directory using:
cd ~/gcc-build-001 time make -j20 |& tee rebuild.log
Test Case Setup
1. Moved to the home directory:
cd ~
2. Created a simple test file named test.c:
int foo(int a) { return a * 2; } int main() { int x = foo(5); return x; }
3. Moved to the GCC build directory and compiled the test file with my custom pass:
cd ~/gcc-build-001/gcc ./xgcc -B. ~/test.c -O2 -fdump-tree-skimv
Issue: No .skim File Found
After compilation, I tried to locate the dump file with:
ls ~/test.c.*.skim cat ~/test.c.*.skim
But the system responded with:
No such file or directory
Fix Attempt: Set OPTGROUP_ALL
I suspected that the issue was due to the dump file not being activated. So, I updated the pass_data declaration like this:
const pass_data pass_data_skim = { GIMPLE_PASS, "skim", OPTGROUP_ALL, // previously OPTGROUP_NONE TV_NONE, PROP_cfg, 0, 0, 0, 0 };
After rebuilding, I still didn’t see the .skim file.
Debugging dump_file
To verify whether the dump_file was being activated, I added this snippet at the top of the execute() function:
if (dump_file == nullptr) { printf("dump_file is null — dump output not activated.\n"); } else { printf("dump_file is active.\n"); }
Then I rebuilt and recompiled again:
cd ~/gcc-build-001 make -j20 cd ~/gcc-build-001/gcc ./xgcc -B. ~/test.c -O2 -fdump-tree-skim
This time, I got the following terminal output:
So, the dump_file was active, meaning the pass was working!
Finding the Actual .skim File
I used this command to search for the actual location of the .skim file:
find ~ -name "*.skim"
That led me to this file:
/home/skim499/gcc-build-001/gcc/a-test.c.264t.skim
When I opened the file, it contained:
This confirmed that:
✅ The -fdump-tree-skim option worked
✅ My custom pass pass_skim was executed
✅ dump_file was active
✅ The output was correctly saved into the .skim file
Notes on the Dump File Name
• The prefix a- seems to be automatically generated by GCC in some builds
• The number 264t indicates the internal pass number where my pass is located
• The .skim extension matches my pass name, so the file was successfully generated
Conclusion
After going through this debugging process, I successfully confirmed that my GIMPLE pass scans all functions and outputs results to both the terminal and the .skim file. This sets the stage for Step 2, where I’ll group and compare cloned functions like foo.default and foo.resolver.
Comments
Post a Comment