What is a compiler A program that reads









- Slides: 9
• What is a compiler? – A program that reads a program written in one language (source language) and translates it into an equivalent program in another language (target language). – Traditionally, the source language is a high level language and the target language is a low level language (machine code). Source program compiler Error message Target program
• Why do we need to learn how a compiler works? – It is very unlikely for anyone to write another C/C++/java compiler. – But … • Parsing a small language occurs quite often: scripts languages such as python, parsing a set of commands for a mail server, etc. • For systems people, the compiler knowledge is the basic requirement. – A new processor is fast because it runs code generated by a compiler fast. – If you implement a new operating system, you need to know how compiler interacts with the OS. An OS is fast because it runs code generated by a compiler fast. – New architectures keep coming: new compiler optimizations are always needed.
• Knowledge required to write a good compiler: – Formal language (lexical analysis and parsing) – Programming language (activation record, scope, type checking, etc) – Algorithm (optimization, register allocation, etc) – Graph theory (optimization, data flow analysis) – Computer architecture (target language, machine dependent optimizations) – Software engineering (large amount of code)
Source program with macros Preprocessor A typical compilation process Source program Compiler Target assembly program assembler Relocatable machine code Loader/link-editor Absolute machine code Try gcc with –v, -E, -S flags On linprog.
Compiler Phases: Source program Lexical analyzer Symbol table manager Front End Syntax analyzer Semantic analyzer Error handler Intermediate code generator Code optimizer Backend Code generator
• Compiler phases: – source program is a stream of characters: pos = init+rate*60 – lexical analysis: groups characters into non-separatable units, called token, and generates token stream: Id 1 = id 2 + id 3 * const • the information about the identifiers must be stored somewhere (symbol table). – Syntax analysis: checks whether the token stream meets the grammatical specification of the language and generates the syntax tree. = Id 1 + id 2 id 3 * 60 – Semantic analysis: checks whether the program has a meaning (e. g. if pos is a record and init and rate are integers then the assignment does not make sense).
• Compiler phases: – intermediate code generation, intermediate code is something that is both close to the final machine code and easy to manipulate (for optimization). One example is the three-address code: dst = op 1 op op 2 • The three-address code for the assignment statement: temp 1 = 60; temp 2 = id 3 + temp 1; temp 3 = id 2 + temp 2; id 1 = temp 3 – Code optimization: produces better/semantically equivalent code. temp 1 = id 3 * 60. 0 id 1 = id 2 + temp 1 – code generator: generates assembly MOVF id 3, R 2 MULF #60. 0, R 2 MOVF id 2, R 1 ADDF R 2, R 1 MOVF R 1, id 1
• The use of intermediate code can also reduce the complexity of compilers: – m front ends and n backends share a common intermediate code. 1 1 2 m Front Ends IC 2 n Backends
• Compiler construction tools: – scanner generator (lex) – parser generator (yacc) – syntax-directed translation engines – automatic code generators – data-flow engines