Understanding the need for an IR
Until this point, we have not properly defined what an IR is and why you need one in a compiler. In this section, we will answer these two questions.
What an IR is
An IR is a data structure suitable for the tasks a compiler needs to do. The right IR depends on what the related compiler is expected to achieve.
For instance, if you build a tool that obfuscates the name of the variables of a C program by replacing them with random names, it might be enough to manipulate a string representing your program. Your transformation does not need to go too deep into the semantics of the input program, and since you support only C programs, you do not need to abstract away the syntax either. Similarly, imagine you build a compiler that translates C programs to assembly code for a specific X86 microarchitecture for a specific operating system (OS). Given the requirement of this tool, there are a lot of things that you do not need to abstract away, such...