Suppose, I have a Pass1 implemented as a subclass of Pass, with source
code in the directory of llvm source base( transform/analyze )
I can run that pass through opt on the bytecode emitted by gcc frontend
through opt tool. However, I want that Pass1 to be the part of the actual GCC
compiler. I want to know how I can position Pass1 among other passes
/optimizations/ code generations.
So when I run llvmgcc , among other transformations, my Pass1 also
runs on the code.
llvm-gcc produces text LLVM assembly, which is then assembled and run
through the gccas tool. If you take a look at
llvm/tools/gccas/gccas.cpp, you will find a list of passes and the order
in which they are run. You can add your pass within the list of passes
you see there.
e.g if I want to run Pass1 before register allocation, then..?
llvm-gcc does not run the register allocator, as that is
machine-specific, and is only done at code-generation time. This means
you are ALREADY running your pass before register allocation if you use
opt, for example:
% llvm-gcc program.c -o program
# you now have 'program' which is a shell script and 'program.bc' which
# is LLVM bytecode. NO register allocation has taken place
% opt -load=/path/to/opt < program.bc > program-transformed.bc
# You now have run your optimization on the code
% llc program-transformed.bc -o program-transformed.s
# You now have run register allocation
FYI, the flow is like this (simplified):
C, C++, etc. => llvm-gcc => gccas (some transformations) => gccld (links
bytecode files together) => opt (optional, some more transformations) =>
llc (native assembly)
Or substitute the jit for llc to get dynamic execution.