Compiler Design - Choosing Intermediate Code
The basic principle of any compiler is to read the source file and to generate compiled code. In practice the compilation process is not so simple. There is a huge leap between the source code written in a high-level language and the desired target code for a particular platform. In general, each high-level statement will be translated to many low-level instructions for our target microprocessor.
In theory, it is possible to directly translate each source code statement to a sequence of microprocessor instructions which will perform the desired result. However, in practice it is better to perform the compilation in two steps. The first step is to process the source code and generate an intermediate code, and in the second step to process this code to generate the final executable code for our target microprocessor. There are many advantages in this approach.
It is a very good idea to have a target-independent intermediate code. This code is usually a description of the high-level statements with some simpler instructions that accurately represent the operations of the source code statements. This code will not execute in a real processor, it is only an internal representation of our high-level program. Since it uses simpler constructs than the high-level language it is much easier to determine the data and control flow. This is very important for optimization algorithms.
Target-independent intermediate code means that for each high-level language that needs to be supported we only have to write the first part of the compiler, the code generator is already written for the intermediate code which does not change. The same applies to the second part, the code generator. If we need to port our compiler to another platform, we only need to write a new code generator for the new processor.