Adding a file to the compilation pipeline
Introduction
This is the first blog post of a series of mini mercurium tutorials, intended to give the audience more information about some, maybe not too well-known features of Mercurium. Today we will start with a feature that enables single source compilation in heterogeneous environments.
Let's assume you have an architecture called N, which we'll call the native architecture (for instance the PPU in a Cell), and several secondary architectures, let's call them A1, .. An (for instance SPU in Cell would be A1). We are assuming, that since you will develop in N, you will have several cross-compilers from N → A{1, .., N} or at least a way to generate from N code for each of the Ai architectures.
When we say single source compilation we mean that the programmer writes once the code and the compilation infrastructure is able to create code for several architectures. This most of the time means that the compiler will offload, or split, part of the code to one these Ai. To achieve this the compiler phase writer has to do something like this
- First, create the source code that will be code to be run in Ai
- Prettyprint this code into a file
- Add the file into the pipeline under a new profile
The compiler uses the profiles, defined in configuration files, as descriptors of these other architectures. So when a new file is added into the pipeline, it is added under one of the existing compiler profiles. The user sets these profiles so they are useful. For instance, we can have a ppucc profile which compiles for PPU and one of its phases creates code for the SPU. This new code will be added in the pipeline to be a file of the spucc profile.
Code for another architecture
The compiler phase developer has some freedom when it concerns to generate additional files to be compiled for other architectures. It is possible to just manage itself the files and then register their names in the compiler pipeline or use some internal facilities of the compiler. These facilities are in the CompiledFile class. Objects of this class can be obtained using CompilationProcess::add_file functions. But you are not forced to use CompiledFile at all, it is just a thin wrapper around a file name. AST_t::prettyprint_into_file uses one of those CompiledFiles, but again to make it clear, you can fill your files the way you prefer.
When using CompilationProcess::add_file one can specify the name of the profile. Here is where we will use the profile we want for some specific architecture.
Example
What follows is a simplified example of our internal project called CellMP, which aims at bringing some Cell goodness to OpenMP style pragmas (or it was the opposite? :). These are the configuration files.
[cellmpcc] language = C options = preprocessor_name = ppu-gcc preprocessor_options = -m32 -E compiler_name = ppu-gcc compiler_options = -m32 -Wall -O2 -ffast-math linker_name = ppu-gcc linker_options = -m32 pragma_prefix = nanos pragma_prefix = spu compiler_phase = libtlnanos.so compiler_phase = libtlcellmp-loops.so compiler_phase = libtlcellmp-analysis.so compiler_phase = libtlcellmp-output.so compiler_phase = libtlomp.so [spucellcc] language = C options = -k preprocessor_name = spu-gcc preprocessor_options = -E compiler_name = spu-gcc compiler_options = -Wall -O2 -ffast-math linker_name = spu-gcc linker_options =
As you can see there are two profiles, one called cellmpcc and another one called spucellc. Phase libtlcellmp-output.so is the responsible to create new files that will be compiled using the profile spucellcc. This phase gets all the information from the previous libtcellmp-analysis.so phase to be able to create a self contained file that can be successfully compiled in the spucellcc profile.
When you type
$ cellmpcc -c test.c
And some code must be created for SPU, an internal file called spu-test.c is created and queued for compilation under the spucellcc profile.
What remains to be done
Maybe you have already noticed it. spucellcc profile does not come with any phase, this is not intentional, currently the compiler is not supporting such scenario. You can see the status of this issue in our tracker. As always your feedback is welcome.
Another issue relates to linking. Linking is something global for the whole application, so we must find a way to link the newly created files, possibly from additional architectures. You can see the status of this issue in our tracker. Again, your feedback is appreciated.
