Cdrec 2
Cdrec 2
AIM :
To write a C program to implement simple code optimization technique (constant
folding etc ..)
ALGORITHM :
STEP 1: Start .
STEP 2: Begin by parsing the source code and generating an abstract syntax tree
(AST) or some intermediate representation that captures the program's structure.
STEP 3: Traverse the AST using a recursive algorithm to visit each node in a bottom-
up manner.
STEP 4: At each node, identify expressions that can be simplified through constant
folding. These expressions include arithmetic operations with known constants on
both sides
STEP 5: For identified expressions, calculate the result of the expression at compile-
time if all operands are constants. Replace the original expression with the computed
constant value.
STEP 6: Continue recursively traversing the tree until you've checked all nodes for
potential constant folding opportunities.
STEP 7: After constant folding, remove any dead code or unused variables to further
optimize the program.
STEP 8: After completing all optimization passes, generate optimized code using
the modified AST or intermediate representation.
STEP 9: Stop.
PROGRAM :
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct op
{
char l;
char r[20];
}
op[10],pr[10];
void main()
{
int a,i,k,j,n,z=0,m,q;
char *p,*l;
char temp,t;
char *tem;
clrscr();
printf("Enter the Number of Values:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("left: ");
op[i].l=getche();
printf("\tright: ");
scanf("%s",op[i].r);
}
printf("Intermediate Code\n") ;
for(i=0;i<n;i++)
{
printf("%c=",op[i].l);
printf("%s\n",op[i].r);
}
for(i=0;i<n-1;i++)
{
temp=op[i].l;
for(j=0;j<n;j++)
{
p=strchr(op[j].r,temp);
if(p)
{
pr[z].l=op[i].l;
strcpy(pr[z].r,op[i].r); z+
+;
}
}
}
pr[z].l=op[n-1].l;
strcpy(pr[z].r,op[n-1].r);
z++;
printf("\nAfter Dead Code Elimination\n");
for(k=0;k<z;k++)
{
printf("%c\t=",pr[k].l);
printf("%s\n",pr[k].r);
}
for(m=0;m<z;m++)
{
tem=pr[m].r;
for(j=m+1;j<z;j++)
{
p=strstr(tem,pr[j].r);
if(p)
{
t=pr[j].l;
pr[j].l=pr[m].l;
for(i=0;i<z;i++)
{
l=strchr(pr[i].r,t) ;
if(l)
{
a=l-pr[i].r;
printf("pos: %d",a);
pr[i].r[a]=pr[m].l;
}
}
}
}
}
printf("Eliminate Common Expression\n");
for(i=0;i<z;i++)
{
printf("%c\t=",pr[i].l);
printf("%s\n",pr[i].r);
}
for(i=0;i<z;i++)
{
for(j=i+1;j<z;j++)
{
q=strcmp(pr[i].r,pr[j].r);
if((pr[i].l==pr[j].l)&&!q)
{
pr[i].l='\0';
strcpy(pr[i].r,'\0');
}
}
}
printf("Optimized Code\n");
for(i=0;i<z;i++)
{
if(pr[i].l!='\0')
{
printf("%c=",pr[i].l);
printf("%s\n",pr[i].r);
}
}
getch();
}
OUTPUT :
RESULT :
Thus the C program to implement simple code optimization technique (constant
folding etc ..) is successfully executed .
EX NO :7
IMPLEMENT THE BACKEND OF THE COMPILER
DATE :
AIM :
To write a C program to implement the back end of the compiler given three address
code as input and 8086 assembly code as output .
ALGORITHM :
STEP 1: Start .
STEP 2: Read and parse the three-address code as input. This code typically consists
of quadruples or triples that represent high-level operations in a simplified format.
STEP 3: Initialize data structures to manage symbol tables, registers, and memory.
STEP 4: Set up the framework for generating assembly code. This may include
initializing the stack, defining the data segment, and setting up any required data
structures to hold variables and constants.
STEP 5: Translate the quadruple into one or more assembly instructions. This
translation depends on the specific operation, the types of operands, and the target
assembly language (8086 in this case).
STEP 6: Implement optimizations like constant propagation, dead code elimination,
and peephole optimizations to improve the generated assembly code's efficiency.
STEP 7: Write the generated assembly code to an output file. The code should
include any initialization, function definitions, and main program logic.
STEP 8 : Stop .
PROGRAM :
#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 \tEnter the set of intermediate code (terminated by exit):\n");
do
{
scanf("%s",icode[i]);
} while(strcmp(icode[i++],"exit")!=0);
printf("\n\t\t target code generation");
printf("\n\t\t************************");
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 C program to implement the back end of the compiler given three address
code as input and 8086 assembly code as output is successfully executed.