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

Compiler Lab Manual

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

Compiler Lab Manual

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

MOHAMED SATHAK ENGINEERING COLLEGE

KILAKARAI – 623 806

DEPARTMENT OF COMPUTER SCIENCE ENGINEERING

CS8602 - COMPILER LABORATORY


(2017 Regulation)

LAB MANUAL

Student Name : _____________________________________

Register Number : _____________________________________

Class : _____________________________________
CS8602 COMPILER LABORATORY LTPC3024

OBJECTIVES:
 To learn the various phases of compiler.
 To learn the various parsing techniques.
 To understand intermediate code generation and run-time environment.
 To learn to implement front-end of the compiler.
 To learn to implement code generator.

LIST OF EXPERIMENTS:
1. Develop a lexical analyzer to recognize a few patterns in C. (Ex. identifiers, constants, comments, operators etc.).
Create a symbol table, while recognizing identifiers.
2. Implement a Lexical Analyzer using Lex Tool
3. Implement an Arithmetic Calculator using LEX and YACC
4. Generate three address code for a simple program using LEX and YACC.
5. Implement simple code optimization techniques (Constant folding, Strength reduction and Algebraic
transformation)
6. Implement back-end of the compiler for which the three address code is given as input and the 8086 assembly
language code is produced as output.
TOTAL: 30 PERIODS
OUTCOMES: Upon completion of the course, the students will be able to:

 Understand the different phases of compiler.


 Design a lexical analyzer for a sample language.
 Apply different parsing algorithms to develop the parsers for a given grammar.
 Understand syntax-directed translation and run-time environment.
 Learn to implement code optimization techniques and a simple code generator.
 Design and implement a scanner and a parser using LEX and YACC tools.

TABLE OF CONTENTS

Exp.No Date Name of the Experiment Page No. Signature

1 Symbol table

2 Lexical analysis recognize in c

3 Lexical analyzer using lex tool

4 Calculator using lex and yacc

Generate three address code for a simple program using


5
LEX and YACC

6 Implement simple code optimization techniques

7 Implement the back end of the compiler


EX.No. : 01 IMPLEMENTATION OF SYMBOL TABLE
DATE :
AIM
To write a C program to implement a symbol table.
INTRODUCTION:
A Symbol table is a data structure used by a language translator such as a compiler or interpreter, where
each identifier in a program‟s source code is associated with information relating to its declaration or appearance in
the source. Possible entries in a symbol table:
 Name : a string
 Attribute:
1. Reserved word
2. Variable name
3. Type Name
4. Procedure name
5. Constant name
 Data type
 Scope information: where it can be used.
 Storage allocation

SYMBOL TABLE
ALGORITHM
1. Start the Program.
2. Get the input from the user with the terminating symbol „$‟.
3. Allocate memory for the variable by dynamic memory allocation function.
4. If the next character of the symbol is an operator then only the memory is allocated.
5. While reading, the input symbol is inserted into symbol table along with its memory address.
6. The steps are repeated till”$”is reached.
7. To reach a variable, enter the variable to the searched and symbol table has been checked for
corresponding variable, the variable along its address is displayed as result.
8. Stop the program.

PROGRAM

#include<stdio.h>
#include<conio.h>
#include<malloc.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
void main()
{
int i=0,j=0,x=0,n,flag=0; void *p,*add[15]; char ch,srch,b[15],d[15],c;
//clrscr();
printf("expression terminated by $:"); while((c=getchar())!='$') {
b[i]=c; i++;
}
n=i-1;
printf("given expression:");
i=0;
while(i<=n)
{
printf("%c",b[i]); i++;
}
printf("symbol table\n");
printf("symbol\taddr\ttype\n");
while(j<=n)
{
c=b[j]; if(isalpha(toascii(c)))
{
if(j==n)
{
p=malloc(c); add[x]=p;
d[x]=c;
printf("%c\t%d\tidentifier\n",c,p);
}
else
{
ch=b[j+1];
if(ch=='+'||ch=='-'||ch=='*'||ch=='=')
{
p=malloc(c);
add[x]=p;
d[x]=c;
printf("%c\t%d\tidentifier\n",c,p);
x++;
}
}
} j++;
}
printf("the symbol is to besearched\n");
srch=getch();
for(i=0;i<=x;i++)
{
if(srch==d[i])
{
printf("symbol found\n");
printf("%c%s%d\n",srch,"@address",add[i]);
flag=1;
}
}
if(flag==0)
printf("symbol not found\n");
//getch();
}

OUTPUT

RESULT:
Thus the C program to implement the symbol table was executed and the output is verified.
EX.No. : 02 DEVELOP A LEXICAL ANALYZER TO RECOGNIZE A FEW PATTERNS IN C
DATE :

AIM
To Write a C program to develop a lexical analyzer to recognize a few patterns in C.

INTRODUCTION:
Lexical analysis is the process of converting a sequence of characters (such as in a computer program of
web page) into a sequence of tokens (strings with an identified “meaning”). A program that perform lexical analysis
may be called a lexer, tokenize or scanner.
TOKEN
A token is a structure representing a lexeme that explicitly indicates its categorization for the Purpose of
parsing. A category of token is what in linguistics might be called a part-of-speech. Examples of token categories
may include “identifier” and “integer literal”, although the set of Token differ in different programming languages.
The process of forming tokens from an input stream of characters is called tokenization.
Consider this expression in the C programming language:

Sum=3 + 2;
Tokenized and represented by the following table:

Lexeme Token category


Sum “identifier”
= “identifier”
3 “integer literal”
+ “addition operator”
2 “integer literal”
; “end of the statement”

ALGORITHM:
1. Start the program
2. Include the header files.
3. Allocate memory for the variable by dynamic memory allocation function.
4. Use the file accessing functions to read the file.
5. Get the input file from the user.
6. Separate all the file contents as tokens and match it with the functions.
7. Define all the keywords in a separate file and name it as key.c
8. Define all the operators in a separate file and name it as open.c
9. Give the input program in a file and name it as input.c
10. Finally print the output after recognizing all the tokens.
11. Stop the program.
PROGRAM
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
void main()
{
FILE *fi,*fo,*fop,*fk;
int flag=0,i=1;
char c,t,a[15],ch[15],file[20];
clrscr();
printf("\n Enter the File Name:");
scanf("%s",&file);
fi=fopen(file,"r");
fo=fopen("inter.c",”r");
fop=fopen("oper.c","r");
fk=fopen("key.c","r");
c=getc(fi);
while(!feof(fi))
{
if(isalpha(c)||isdigit(c)||(c=='['||c==']'||c=='.'==1))
fputc(c,fo);
else
{
if(c=='\n')
fprintf(fo,"\t$\t");
else fprintf(fo,"\t%c\t",c);
}
c=getc(fi);

}
fclose(fi);
fclose(fo);
fi=fopen("inter.c","r");
printf("\n Lexical Analysis");
fscanf(fi,"%s",a);
printf("\n Line: %d\n",i++);
while(!feof(fi))
{
if(strcmp(a,"$")==0)
{
printf("\n Line: %d \n",i++);
fscanf(fi,"%s",a);
}
fscanf(fop,"%s",ch);
while(!feof(fop))
{
if(strcmp(ch,a)==0)
{
fscanf(fop,"%s",ch);
printf("\t\t%s\t:\t%s\n",a,ch);
flag=1;
} fscanf(fop,"%s",ch);
}
rewind(fop);
fscanf(fk,"%s",ch);
while(!feof(fk))
{
if(strcmp(ch,a)==0)
{
fscanf(fk,"%k",ch);
printf("\t\t%s\t:\tKeyword\n",a);
flag=1;
}
fscanf(fk,"%s",ch);
}
rewind(fk);
if(flag==0)
{
if(isdigit(a[0]))
printf("\t\t%s\t:\tConstant\n",a);
else
printf("\t\t%s\t:\tIdentifier\n",a);
}
flag=0;
fscanf(fi,"%s",a); }
getch();
}
Key.C:
Int
void
main
char
if
for
while
else
printf
scanf
FILE
Include stdio.h
conio.h
iostream.h
Oper.C:
( open para
) closepara
{ openbrace } closebrace < lesser
> greater
" doublequote ' singlequote : colon
; semicolon
# preprocessor = equal
== asign
% percentage ^ bitwise
& reference * star
+ add - sub
\ backslash / slash

Input.C:
#include "stdio.h"
#include "conio.h"
void main()
{
int a=10,b,c;
a=b*c;
getch();
}

OUTPUT:

RESULT:

Thus the above program for developing the lexical the lexical analyzer and recognizing the few
pattern s in C is executed successfully and the output is verified.
EX.NO:3 IMPLEMENTATION OF LEXICAL ANALYZER USING LEX TOOL
DATE:

AIM:
To write a program to implement the Lexical Analyzer using lex tool.

INTRODUCTION:
THEORY:
 A language for specifying lexical analyzer.
 There is a wide range of tools for construction of lexical analyzer. The majority of these tools
are based on regular expressions.
 The one of the traditional tools of that kind is lex.

LEX:
 The lex is used in the manner depicted. A specification of the lexical analyzer is preferred by
creating a program lex.1 in the lex language.

 Then lex.1 is run through the lex compiler to produce a „c‟ program lex.yy.c.

 The program lex.yy.c consists of a tabular representation of a transition diagram constructed from
the regular expression of lex.1 together with a standard routine that uses table of recognize
leximes.
 Lex.yy.c is run through the „C‟ compiler to produce as object program a.out, which is the lexical
analyzer that transform as input stream into sequence of tokens.
LEX SOURCE:
ALGORITHM:

1. Start the program


2. Lex program consists of three parts.
3. Declaration %%
4. Translation rules %%
5. Auxiliary procedure.
6. The declaration section includes declaration of variables, main test, constants and regular
7. Definitions.
8. Translation rule of lex program are statements of the form
9. P1{action}
10. P2{action}
11. …..
12. …..
13. Pn{action}
14. Write program in the vi editor and save it with .1 extension.
15. Compile the lex program with lex compiler to produce output file as lex.yy.c.
16. Eg. $ lex filename.1
17. $gcc lex.yy.c-11
18. Compile that file with C compiler and verify the output.

PROGRAM: (LEXICAL ANALYZER USING LEX TOOL)


#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<string.h>
char vars[100][100];
int vcnt;
char input[1000],c;
char token[50],tlen;
int state=0,pos=0,i=0,id;
char *getAddress(char str[])
{
for(i=0;i<vcnt;i++)
if(strcmp(str,vars[i])==0)
return vars[i];
strcpy(vars[vcnt],str);
return vars[vcnt++];
}
int isrelop(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^')
return 1;
else
return 0;
}
int main(void)
{
clrscr();
printf("Enter the Input String:");
gets(input);
do
{
c=input[pos];
putchar(c);
switch(state)
{
case 0:
if(isspace(c))
printf("\b");
if(isalpha(c))
{
token[0]=c;
tlen=1;
state=1;
}
if(isdigit(c))
state=2;
if(isrelop(c))
state=3;
if(c==';')
printf("\t<3,3>\n");
if(c=='=')
printf("\t<4,4>\n");
break;
case 1:
if(!isalnum(c))
{
token[tlen]='\o';
printf("\b\t<1,%p>\n",getAddress(token));
state=0;
pos--;
}
else
token[tlen++]=c;
break;
case 2:
if(!isdigit(c))
{
printf("\b\t<2,%p>\n",&input[pos]);
state=0;
pos--;
}
break;
case 3:
id=input[pos-1];
if(c=='=')
printf("\t<%d,%d>\n",id*10,id*10);
else{
printf("\b\t<%d,%d>\n",id,id);
pos--;
}state=0;
break;
}
pos++;
}
while(c!=0);
getch();
return 0;
}
OUTPUT

RESULT:
Thus the program for the exercise on lexical analysis using lex has been successfully executed and output
is verified.
EX.NO:4 IMPLEMENTATION OF CALCULATOR USING LEX AND YACC
DATE:

AIM :
To write a c program to do exercise on syntax analysis using YACC.

INTRODUCTION:
YACC (yet another compiler) is a program designed to produce designed to compile a LALR (1) grammar
and to produce the source code of the synthetically analyses of the language produced by the grammar.

ALGORITHM :
1. Start the program.
2. Write the code for parser. l in the declaration port.
3. Write the code for the „y‟ parser.
4. Also write the code for different arithmetical operations.
5. Write additional code to print the result of computation.
6. Execute and verify it.
7. Stop the program.
PROGRAM:
%{
#include<stdio.h>
int op=0,i;
float a,b;
%}
dig[0-9]+|([0-9]*)"."([0-9]+)
add "+"
sub "-"
mul"*"
div "/"
pow "^"
ln \n
%%
{dig}{digi();}
{add}{op=1;}
{sub}{op=2;}
{mul}{op=3;}
{div}{op=4;}
{pow}{op=5;}
{ln}{printf("\n the result:%f\n\n",a);}
%%
digi()
{
if(op==0)
a=atof(yytext);

else
{
b=atof(yytext);
switch(op)
{
case 1:a=a+b;
break;
case 2:a=a-b;
break;
case 3:a=a*b;
break;
case 4:a=a/b;
break;
case 5:for(i=a;b>1;b--)
a=a*i;
break;
}
op=0;
}
}
main(int argv,char *argc[])
{
yylex();
}
yywrap()
{ return 1;
}
OUTPUT:
Lex cal.l
Cc lex.yy.c-ll
a.out
4*8
The result=32

RESULT:

Thus the program for the exercise on the syntax using YACC has been executed
Successfully and Output is verified.
EX.NO:5 GENERATE THREE ADDRESS CODE FOR A SIMPLE PROGRAM USING LEX and YACC
DATE:

Aim:

To write a C program to generate three address code for a simple program using LEX and YACC.

Algorithm:
1. Start the program
2. Open the source file and store the contents as quadruples.
3. Check for operators, in quadruples, if it is an arithmetic operator generator it or if assignment
operator generates it, else perform unary minus on register C.
4. Write the generated code into output definition of the file in outp.c
5. Print the output.
6. Stop the program.
Program

(TAC.l)

%{

#include <stdio.h>

#include <string.h>

%}

LETTER [A-Za-z]

DIGIT [0-9]

OPERATOR [+-*/=<>&|!(){}]

FOR "for"

WHILE "while"

IF "if"

DO "do"

ELSE "else"

THEN "then"

%%

{LETTER} {strcpy(yylval.id,yytext);
return LETTER;}

{DIGIT}+"."{DIGIT}+ {strcpy(yylval.id,yytext);

return FLOAT;}

{DIGIT}+ {strcpy(yylval.id,yytext);

return INTEGER;}

{FOR} {return FOR;}

{WHILE} {return WHILE;}

{DO} {return DO;}

{IF} {return IF;}

{THEN} {return THEN;}

{ELSE} {return ELSE;}

[ \n\t]* ;

"end" {return 0;}

%%

(TAC.y)

%{

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<ctype.h>

#include<math.h>

#define START 100

typedef struct s

int* true;

int* false;

int* next;

int quad;

char place[5];
}ETYPE;

int nextquad=START;

char code[25][50];

%}

%union

char id[10];

ETYPE eval;

%left "|"

%left "&"

%left "!"

%left "<" ">"

%left "+" "-"

%left "*" "/"

%left "(" ")"

%right "="

%token <id> LETTER INTEGER FLOAT

%token FOR WHILE DO IF THEN ELSE

%type <eval> PROGRAM BLOCK STATEMENTS ASSIGN COND LVAL E M N Q

%start PROGRAM

%%

PROGRAM: BLOCK {

int i;

Backpatch($1.next,nextquad);

for(i=START;i<nextquad;i++)

printf("\n%s",code[i-START]);

printf("\n%d\n",nextquad);

}
BLOCK: DO M BLOCK WHILE M COND {

Backpatch($6.true,$2.quad);

$$.next=$6.false;

| FOR ASSIGN M COND M ASSIGN Q BLOCK {

Backpatch($8.next,$5.quad);

Backpatch($6.next,$3.quad);

Backpatch($4.true,$7.quad);

$$.next=$4.false;

sprintf(code[nextquad-START],"%d\tgoto %d",nextquad,$5.quad);

Gen();

| WHILE M COND M BLOCK {

Backpatch($5.next,$2.quad);

Backpatch($3.true,$4.quad);

$$.next=$3.false;

sprintf(code[nextquad-START],"%d\tgoto %d",nextquad,$2.quad);

Gen();

| IF COND M BLOCK {

Backpatch($2.true,$3.quad);

$$.next=Merge($2.false,$4.next);

| IF COND M BLOCK N ELSE M BLOCK {

Backpatch($2.true,$3.quad);

Backpatch($2.false,$7.quad);

$$.next=Merge($4.next,$5.next);

$$.next=Merge($$.next,$8.next);

}
| '{' STATEMENTS '}' {

$$.next=$2.next;

| ASSIGN ';' {

$$.next=(int*)malloc(sizeof(int)*15);

$$.next[0]=0;

|E{}

STATEMENTS: STATEMENTS M BLOCK {

Backpatch($1.next,$2.quad);

$$.next=$3.next;

| BLOCK {

$$.next=$1.next;

ASSIGN: LVAL '=' E {

sprintf(code[nextquad-START],"%d\t%s = %s",nextquad,$1.place,$3.place);

Gen();

|E{}

LVAL: LETTER {strcpy($$.place,$1);}

E: E '+' E {

strcpy($$.place,Newtemp());

sprintf(code[nextquad-START],"%d\t%s = %s + %s",nextquad,$$.place,$1.place,$3.place);

Gen();

| E '-' E {

strcpy($$.place,Newtemp());

sprintf(code[nextquad-START],"%d\t%s = %s - %s",nextquad,$$.place,$1.place,$3.place);
Gen();

| E '*' E {

strcpy($$.place,Newtemp());

sprintf(code[nextquad-START],"%d\t%s = %s * %s",nextquad,$$.place,$1.place,$3.place);

Gen();

| E '/' E {

strcpy($$.place,Newtemp());

sprintf(code[nextquad-START],"%d\t%s = %s / %s",nextquad,$$.place,$1.place,$3.place);

Gen();

| '-' E %prec '*' {

strcpy($$.place,Newtemp());

sprintf(code[nextquad-START],"%d\t%s = - %s",nextquad,$$.place,$2.place);

Gen();

| LETTER {

strcpy($$.place,$1);

| INTEGER {

strcpy($$.place,$1);

| FLOAT {

strcpy($$.place,$1);

COND: COND '&' M COND {

Backpatch($1.true,$3.quad);

$$.true=$4.true;
$$.false=Merge($1.false,$4.false);

| COND '|' M COND {

Backpatch($1.false,$3.quad);

$$.true=Merge($1.true,$4.true);

$$.false=$4.false;

| '!' COND {

$$.true=$2.false;

$$.false=$2.true;

| '(' COND ')' {

$$.true=$2.true;

$$.false=$2.false;

| E '<' E {

$$.true=Makelist(nextquad);

$$.false=Makelist(nextquad+1);

sprintf(code[nextquad-START],"%d\tif %s < %s goto ",nextquad,$1.place,$3.place);

Gen();

sprintf(code[nextquad-START],"%d\tgoto ",nextquad);

Gen();

| E '>' E {

$$.true=Makelist(nextquad);

$$.false=Makelist(nextquad+1);

sprintf(code[nextquad-START],"%d\tif %s > %s goto ",nextquad,$1.place,$3.place);

Gen();

sprintf(code[nextquad-START],"%d\tgoto ",nextquad);
Gen();

|E{

$$.true=Makelist(nextquad);

$$.false=Makelist(nextquad+1);

sprintf(code[nextquad-START],"%d\tif %s goto ",nextquad,$1.place);

Gen();

sprintf(code[nextquad-START],"%d\tgoto ",nextquad);

Gen();

M: {

$$.quad=nextquad;

N: {

$$.next=Makelist(nextquad);

sprintf(code[nextquad-START],"%d\tgoto ",nextquad);

Gen();

Q: {

$$.next=Makelist(nextquad);

sprintf(code[nextquad-START],"%d\tgoto ",nextquad);

Gen();

$$.quad=nextquad;

%%

/*

#include "lex.yy.c"

main()

{
yyparse();

*/

yyerror(char *errmesg)

printf("\n%s\n",errmesg);

char* Newtemp()

static int count=1;

char* ch=(char*)malloc(sizeof(char)*5);

sprintf(ch,"T%d",count++);

return ch;

int* Makelist(int nquad)

int* list=(int*)malloc(sizeof(int)*15);

list[0]=nquad;

list[1]=0;

return list;

int* Merge(int* list1,int* list2)

int* temp=list1,count1=0,count2=0;

while(list1[count1]!=0) count1++;

while(list1[count2]!=0)

list1[count1]=list2[count2];

count1++;
count2++;

return temp;

void Backpatch(int* list,int nquad)

char addr[10];

sprintf(addr,"%d",nquad);

while(*list!=0)

int index=*list++-START;

strcat(code[index],addr);

void Gen()

nextquad++;

}
EX.NO:6 IMPLEMENTATION OF SIMPLE CODE OPTIMIZATION TECHNIQUES
DATE:

AIM:
To write a C program to implement simple code optimization technique.

INTRODUCTION:
Optimization is a program transformation technique, which tries to improve the code by making it consume
less resource (i.e. CPU, memory) and deliver high speed.
In optimization, high-level general programming constructs are replaced by very efficient low level
programming codes. A code optimizing process must follow the three rules given below:
The output code must not, in any way, change the meaning of the program.
 Optimization should increases the speed of the program and if possible, the program should demand
less number of resources.
 Optimization should itself be fast and fast and should not delay the overall compiling process.
Efforts for an optimized code can be made at various levels of compiling the process.
 At the beginning, users can change/rearrange the code or use better algorithms to write the code.
 After generating intermediate code, the compiler can modify the intermediate code by address
calculations and improving loops.
 While producing the target machine code, the compiler can make use of memory hierarchy and cpu
registers.
Optimization can be categorized broadly into two types: Machine independent and Machine dependent.
Machine independent optimization
In this optimization, the compiler takes in the intermediate code and transforms a part of the code that does
not involve any CPU registers and/or absolute memory locations.
For Example:
do
{
item=10;
value=value+item;
}while(value<100);
This code involves repeated assignment of the identifier item, which if we put this way:
item=10;
do
{
value=value+item;
}while(value<100);
Should not only save the cpu cycles, but can be used on any processor.
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
memory hierarchy.

ALGORITHM:
1. Start the program
2. Declare the variables and functions.
3. Enter the expressionand state it in the variable a, b, c.
4. Calculate the variables b & c with „temp‟ and store it in f1 and f2.
5. If(f1=null && f2=null) then expression could not be optimized.
6. Print the results.
7. Stop the program.
PROGRAM: (SIMPLE CODE OPTIMIZATION TECHNIQUE) Before: Using for :
#include<iostream.h>
#include <conio.h>
int main()
{
int i, n;
int fact=1;
cout<<"\nEnter a number: ";
cin>>n;
for(i=n;i>=1;i--)
fact=fact *i;
cout<<"The factoral value is: "<<fact;
getch();
return 0;
}
OUTPUT:

After: (SIMPLE CODE OPTIMIZATION TECHNIQUE) Using do-while:

#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
int n,f;
f=1;
cout<<"Enter the number:\n";
cin>>n;
do
{
f=f*n;
n--;
}while(n>0);
cout<<"The factorial value is:"<<f;
getch();
}
OUTPUT:

RESULT:

Thus the Simple Code optimization technique is successfully executed


EX.NO.7 IMPLEMENT THE BACK END OF THE COMPILER
DATE:

AIM:
To implement the back end of the compiler which takes the three address code and produces the 8086
assembly language instructions that can be assembled and run using a 8086 assembler. The target assembly
instructions can be simple move, add, sub, jump. Also simple addressing modes are used.
INTRODUCTION:
A compiler is a computer program that implements a programming language specification to “translate”
programs, usually as a set of files which constitute the source code written in source language, into their equivalent
machine readable instructions(the target language, often having a binary form known as object code). This
translation process is called compilation.
BACK END:
 Some local optimization
 Register allocation
 Peep-hole optimization
 Code generation
 Instruction scheduling
The main phases of the back end include the following:
 Analysis: This is the gathering of program information from the intermediate representation derived
from the input; data-flow analysis is used to build use-define chains, together with dependence
analysis, alias analysis, pointer analysis, escape analysis etc.
 Optimization: The intermediate language representation is transformed into functionally equivalent
but faster (or smaller) forms. Popular optimizations are expansion, dead, constant, propagation, loop
transformation, register allocation and even automatic parallelization.
 Code generation: The transformed language is translated into the output language, usually the native
machine language of the system. This involves resource and storage decisions, such as deciding
which variables to fit into registers and memory and the selection and scheduling of appropriate
machine instructions along with their associated modes. Debug data may also need to be generated
to facilitate debugging.
ALGORITHM:
7. Start the program
8. Open the source file and store the contents as quadruples.
9. Check for operators, in quadruples, if it is an arithmetic operator generator it or if assignment
operator generates it, else perform unary minus on register C.
10. Write the generated code into output definition of the file in outp.c
11. Print the output.
12. Stop the program.
PROGRAM: (BACK END OF THE COMPILER)
#include<stdio.h>
#include<stdio.h>
//#include<conio.h>
#include<string.h>
void main()
{
char icode[10][30],str[20],opr[10];
int i=0;
//clrscr();
printf("\n Enter the set of intermediate code (terminated by exit):\n");
do
{
scanf("%s",icode[i]);
} while(strcmp(icode[i++],"exit")!=0);
printf("\n target code generation");
printf("\n************************");
i=0;
do
{
strcpy(str,icode[i]);
switch(str[3])
{
case '+':
strcpy(opr,"ADD");
break;
case '-':
strcpy(opr,"SUB");
break;
case '*':
strcpy(opr,"MUL");
break;
case '/':
strcpy(opr,"DIV");
break;
}
printf("\n\tMov %c,R%d",str[2],i);
printf("\n\t%s%c,R%d",opr,str[4],i);
printf("\n\tMov R%d,%c",i,str[0]);
}while(strcmp(icode[++i],"exit")!=0);
//getch();
}

OUTPUT:

RESULT:
Thus the program was implemented to the TAC has been successfully executed.

You might also like