0% found this document useful (0 votes)
49 views14 pages

Introduction To Compilers

The document discusses the structure and tasks of a compiler. It explains that a compiler has a front end that analyzes and parses source code, and a back end that generates target code. It provides examples of lexical analysis, parsing, code generation and optimization phases in a compiler.

Uploaded by

shvdo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views14 pages

Introduction To Compilers

The document discusses the structure and tasks of a compiler. It explains that a compiler has a front end that analyzes and parses source code, and a back end that generates target code. It provides examples of lexical analysis, parsing, code generation and optimization phases in a compiler.

Uploaded by

shvdo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 14

Main Goal

• Reading: Chapter 1
• How do we execute something like this?
int nPos = 0;
int k = 0; while (k < length) {
if (a[k] > 0) {
nPos++;
}
}
• Or, more concretely, how do we program a computer to understand and
carry out a computation written as text in a file? The computer only
knows 1’s & 0’s: encodings of instructions and data
Structure of a Compiler
At a high level, a compiler has two pieces:
– Front end: analysis
• Read source program and discover its structure and meaning
– Back end: synthesis
• Generate equivalent target language program
Compiler Tasks

• Recognize legal programs (& complain about illegal


ones)
• Generate correct code
– Compiler can attempt to improve (“optimize”)
code, but must not change behavior (meaning)
• Manage runtime storage of all variables/data
• Agree with OS & linker on target format
Front End

• Usually split into two parts


– Scanner: Responsible for converting character stream to token stream:
keywords, operators, variables, constants, …
• Also: strips out white space, comments
– Parser: Reads token stream; generates IR (Intermediate representation)
• Either here or shortly after, perform semantics analysis to check for things like type errors, etc.

• Both of these can be generated automatically


– Use a formal grammar to specify the source language
– Tools read the grammar and generate scanner & parser (lex/yacc or
flex/bison for C/C++, JFlex/CUP for Java)
Scanner Example
• Input text
// this statement does very little
if (x >= y) y = 42;
• Token Stream

• Notes:
• tokens are atomic items, not character strings; comments & whitespace are
not tokens (in most languages – counterexamples: Python indenting, Ruby
and JavaScript newlines)
• Token objects sometimes carry associated data (e.g., numeric value, variable
name)
Parser Output (IR)
• Given token stream from scanner, the parser must produce output
that captures the meaning of the program
• Most common parser output is an abstract syntax tree (AST)
– Essential meaning of program without syntactic noise
– Nodes are operations, children are operands
• Many different forms
– Tradeoffs change over time
– Tradeoffs (and IRs) can also vary between different phases of a single compiler
Scanner/Parser Example
Static Semantic Analysis
• During or (usually) after parsing, check that the program is legal and
collect info for the back end
– Type checking
– Verify language requirements like proper declarations, etc.
– Preliminary resource allocation
– Collect other information needed by back end analysis and code generation
• Key data structure: Symbol Table(s)
– Maps names -> meaning/types/details
Back End
• Responsibilities
– Translate IR into target code
– Should produce “good” code
• “good” = fast, compact, low power (pick
some)
– Should use machine resources effectively
• Registers
• Instructions
• Memory hierarchy
Back End Structure
• Typically two major parts
– “Optimization” – code improvement – change correct code into
semantically equivalent “better” code
• Examples: common subexpression elimination, constant folding, code motion
(move invariant computations outside of loops), function inlining (replace call with
body of function)
• Optimization phases often interleaved with analysis
– Target Code Generation (machine specific)
• Instruction selection & scheduling, register allocation
• Usually walk the AST and generate lower-level intermediate code before
optimization
Example
Example
Why Study Compilers?
• Become a better programmer
– Insight into interaction between languages, compilers, and hardware
– Better intuition about what your code does
– Understanding how compilers optimize code helps you write code that is easier to optimize
• Compiler techniques are everywhere
– Parsing (“little” languages, program input, scripts,…)
– Software tools (verifiers, checkers, …)
– Database engines, query languages
– Text processing
• Tex/LaTex -> dvi -> Postscript -> pdf
• Interesting challenges
– Ordering of optimization phases
– register allocation is NP-Hard
• You might even write a compiler some day
Compilers Draws ideas from many CS Areas
• AI: Greedy algorithms, heuristic search
• Algorithms: graphs, dynamic programming, approximation
• Theory: Grammars, DFAs and PDAs, pattern matching, fixed-point algorithms
• Systems: Allocation & naming, synchronization, locality
• Architecture: pipelines, instruction set use, memory hierarchy management,
locality

You might also like