Translating a program
Programmers describe calculations through variables, expressions, and functions, while a processor executes a particular instruction set. A compiler bridges representations rather than merely replacing individual words. Its output can be assembly, bytecode, or another language. Translation therefore does not necessarily produce a complete executable for the current computer.
Building a structural representation
A frontend recognizes tokens and determines how expressions fit together. An abstract syntax tree records relationships such as which multiplication supplies an addition, rather than preserving only a sequence of characters. LLVM’s introductory compiler uses recursive-descent and precedence parsing to build this representation before later code generation.
References: [2]
Compilation, assembly, and linking
GCC distinguishes preprocessing, compilation proper, assembly, and linking, and can stop after intermediate stages. An assembler produces object files; a linker combines them and resolves required symbols. A missing library symbol at link time is consequently different from a malformed source expression encountered while parsing.
References: [1]
Sharing intermediate representations
Separating the frontend from later representations permits components to be reused across languages or targets. Transformations must preserve the behavior required by the source language. Libraries, loaders, and execution environments still have their own responsibilities: successful compilation is one part of a working software system.