0% found this document useful (0 votes)
533 views

Compiler Design

The document discusses the phases of a compiler, including the analysis phase which creates an intermediate representation from source code, and the synthesis phase which creates a target program from the intermediate representation. It also describes the main components of a compiler's front-end, including the lexical analyzer, syntax analyzer, semantic analyzer, and intermediate code generator, and the back-end components including code optimization and target code generation.

Uploaded by

SHIVANI KOTHARI
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
533 views

Compiler Design

The document discusses the phases of a compiler, including the analysis phase which creates an intermediate representation from source code, and the synthesis phase which creates a target program from the intermediate representation. It also describes the main components of a compiler's front-end, including the lexical analyzer, syntax analyzer, semantic analyzer, and intermediate code generator, and the back-end components including code optimization and target code generation.

Uploaded by

SHIVANI KOTHARI
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

Compiler design: -

Phases of a Compiler
Prerequisite – Introduction of Compiler design
We basically have two phases of compilers, namely Analysis phase and Synthesis
phase. Analysis phase creates an intermediate representation from the given source
code. Synthesis phase creates an equivalent target program from the intermediate
representation.
Symbol Table – It is a data structure being used and maintained by the compiler,
consists all the identifier’s name along with their types. It helps the compiler to
function smoothly by finding the identifiers quickly.
The compiler has two modules namely front end and back end. Front-end constitutes
of the Lexical analyzer, semantic analyzer, syntax analyzer and intermediate code
generator. And the rest are assembled to form the back end.
1. Lexical Analyzer –
It is also called scanner. It takes the output of preprocessor (which performs file
inclusion and macro expansion) as the input which is in pure high level
language. It reads the characters from source program and groups them into
lexemes (sequence of characters that “go together”). Each lexeme corresponds
to a token. Tokens are defined by regular expressions which are understood by
the lexical analyzer. It also removes lexical errors (for e.g. erroneous
characters), comments and white space.
2. Syntax Analyzer – It is sometimes called as parser. It constructs the parse
tree. It takes all the tokens one by one and uses Context Free Grammar to
construct the parse tree.
Why Grammar ?
The rules of programming can be entirely represented in some few productions.
Using these productions we can represent what the program actually is. The
input has to be checked whether it is in the desired format or not.
Syntax error can be detected at this level if the input is not in accordance with
the grammar.

3. Semantic Analyzer – It verifies the parse tree, whether it’s meaningful or not.
It furthermore produces a verified parse tree.It also does type checking, Label
checking and Flow control checking.
4. Intermediate Code Generator – It generates intermediate code, that is a
form which can be readily executed by machine We have many popular
intermediate codes. Example – Three address code etc. Intermediate code is
converted to machine language using the last two phases which are platform
dependent.
Till intermediate code, it is same for every compiler out there, but after that, it
depends on the platform. To build a new compiler we don’t need to build it from
scratch. We can take the intermediate code from the already existing compiler
and build the last two parts.
5. Code Optimizer – It transforms the code so that it consumes fewer resources
and produces more speed. The meaning of the code being transformed is not
altered. Optimisation can be categorized into two types: machine dependent
and machine independent.
6. Target Code Generator – The main purpose of Target Code generator is to
write a code that the machine can understand and also register allocation,
instruction selection etc. The output is dependent on the type of assembler.
This is the final stage of compilation.
\

Ans 2: -

Some commonly used compiler-construction tools. include


1. Parser generators.
2. Scanner generators.
3. Syntax-directed translation engines.
4. Automatic code generators.
5. Data-flow analysis engines.
6. Compiler-construction toolkits.

Parser Generators
Input: Grammatical description of a programming language
Output: Syntax analyzers.
Parser generator takes the grammatical description of a programming language and
produces a syntax analyzer.

Scanner Generators
Input: Regular expression description of the tokens of a language
Output: Lexical analyzers.
Scanner generator generates lexical analyzers from a regular expression
description of the tokens of a language.

Syntax-directed Translation Engines


Input: Parse tree.
Output: Intermediate code.
Syntax-directed translation engines produce collections of routines that walk a
parse tree and generates intermediate code.

Automatic Code Generators


Input: Intermediate language.
Output: Machine language.
Code-generator takes a collection of rules that define the translation of each
operation of the intermediate language into the machine language for a target
machine.
Data-flow Analysis Engines
Data-flow analysis engine gathers the information, that is, the values transmitted
from one part of a program to each of the other parts. Data-flow analysis is a key
part of code optimization.

Compiler Construction Toolkits


The toolkits provide integrated set of routines for various phases of compiler.
Compiler construction toolkits provide an integrated set of routines for
construction of phases of compiler.
Ans 3:-

Code Optimization in Compiler Design


The code optimization in the synthesis phase is a program transformation technique,
which tries to improve the intermediate code by making it consume fewer resources
(i.e. CPU, Memory) so that faster-running machine code will result. Compiler
optimizing process should meet the following objectives :
 The optimization must be correct, it must not, in any way, change the meaning
of the program.
 Optimization should increase the speed and performance of the program.
 The compilation time must be kept reasonable.
 The optimization process should not delay the overall compiling process.
When to Optimize?
Optimization of the code is often performed at the end of the development stage
since it reduces readability and adds code that is used to increase the performance.
Types of Code Optimization –The optimization process can be broadly classified
into two types :

1. Machine Independent Optimization – This code optimization phase


attempts to improve the intermediate code to get a better target code as the
output. The part of the intermediate code which is transformed here does not
involve any CPU registers or absolute memory locations.
2. Machine Dependent Optimization – Machine-dependent optimization is
done after the target code has been generated and when the code is
transformed according to the target machine architecture. It involves CPU
registers and may have absolute memory references rather than relative
references. Machine-dependent optimizers put efforts to take
maximum advantage of the memory hierarchy.
Code Optimization is done in the following different ways :
1. Compile Time Evaluation :
filter_none
brightness_4
(i)  A = 2*(22.0/7.0)*r 
     Perform 2*(22.0/7.0)*r at compile time.
(ii)  x = 12.4
      y = x/2.3 
      Evaluate x/2.3 as 12.4/2.3 at compile time.
2. Variable Propagation :
filter_none
brightness_4
//Before Optimization 
c = a * b                                               
x = a                                                  
till                                                           
d = x * b + 4 
 
 
//After Optimization 
c = a * b  
x = a
till
d = a * b + 4
Hence, after variable propagation, a*b and x*b will be identified as common
sub-expression.
3. Dead code elimination : Variable propagation often leads to making
assignment statement into dead code
filter_none
brightness_4
c = a * b                                                
x = a                                                
till                                                          
d = a * b + 4   
 
//After elimination :
c = a * b
till
d = a * b + 4
4. Code Motion :
• Reduce the evaluation frequency of expression.
• Bring loop invariant statements out of the loop.
filter_none
brightness_4
a = 200;
 while(a>0)
 {
     b = x + y;
     if (a % b == 0}
     printf(“%d”, a);
   }
 
 
//This code can be further optimized as
a = 200;
b = x + y;
while(a>0)
 {
     if (a % b == 0}
     printf(“%d”, a);
   }
5. Induction Variable and Strength Reduction :
• An induction variable is used in loop for the following kind of assignment i = i +
constant.
• Strength reduction means replacing the high strength operator by the low
strength.
filter_none
brightness_4
i = 1;                                                                      
while (i<10)                                                          
{                                                                             
    y = i * 4; 
}
  
  
//After Reduction
i = 1
t = 4

   while( t<40) 
   y = t; 
   t = t + 4;
}
Ans 4: -

You might also like