Modern compilers can insert information about the source code into the executable program. This information is used by powerful source-level debugger s to show exactly what is happening in a program by tracing its progress through the source code. Most compilers work with files, reading and writing them in each step of the compilation process. For small programs, this can seem as responsive as an interpreter. The pre-processed code is often written to an intermediate file.
Compilers usually do their work in two passes.
The first pass parses the pre-processed code. The compiler breaks the source code into small units and organizes it into a structure called a tree . A global optimizer is sometimes used between the first and second passes to produce smaller, faster code. In the second pass, the code generator walks through the parse tree and generates either assembly language code or machine code for the nodes of the tree. If the code generator creates assembly code, the assembler must then be run.