Académique Documents
Professionnel Documents
Culture Documents
SUB:-SYSTEM SOFTWARE
Topic:-SOURCE TO SOURCE COMPILER
Submitted By
CHETAN ANAND
RD1801A08
Reg.No-10808811
Submitted To
Ms.Neha Tewari
TABLE OF CONTENT
1. COMPILER
• Structure of compiler
• One pass Vs multi-pass
compiler
2. SOURSE TO SOURSE
COMPILER
• Defination
• Purpose
• Symbolic Manipulation
• Analyses Transformation
Compiler
A compiler is a computer program or set of programs that
transforms source code written in a programming language
into another computer language known as object code. The
most common reason for wanting to transform source code is
to create an executable program.
1. lexical analysis
2. preprocessing
3. parsing
4. semantic analysis
5. code generation
6. code optimization.
3) run-time organization,
While the typical multi-pass compiler outputs machine code from its final
pass, there are several other types:
A "source-to-source compiler" is a type of compiler that takes a high
level language as its input and outputs a high level language. For
example, an automatic parallelizing compiler will frequently take in a
high level language program as an input and then transform the code
and annotate it with parallel code annotations or language constructs.
Stage compiler that compiles to assembly language of a theoretical
machine, like some Prolog implementations
This Prolog machine is also known as the Warren Abstract
Machine (or WAM).
Bytecode compilers for Java, Python, and many more are also
a subtype of this.
Just-in-time compiler, used by Smalltalk and Java systems, and also
by Microsoft .NET's Common Intermediate Language (CIL)
Source-to-source compiler
Defination
A source-to-source compiler is a type of compiler that takes a
high level programming language as its input and outputs a
high level language. For example, an automatic parallelizing
compiler will frequently take in a high level language program
as an input and then transform the code and annotate it with
parallel code annotations e.g. OpenMP or language constructs
e.g. Fortran's DOALL statements.
Purpose
Purpose of source-to-source-compiling is translating legacy
code to use the next version of the underlying programming
language or an API that breaks backward compatibility.
Examples of this are seen in Python 3000 or Qt's qt3to4 tool.
EG:
% llvm-g++ x.cpp -o program
% llc -march=c program.bc -o program.c
% cc x.c
Symbolic Manipulation
Like its predecessor Polaris [1, 2], a key feature of Cetus is its ability to
reason
about the represented program in symbolic terms. For example, program
analysis
and optimization techniques at the source level often require the
expressions in
the program to be in a simpli_ed form. A speci_c example is a data
dependence
test which collects the coe_cients of a_ne subscript expressions to
interface
with the underlying data dependence solvers. Cetus supports such
expression
manipulations by providing a set of utilities that simplify and normalize
symbolic
expressions. .
class Instrumenter
{
...
public void instrumentLoops(Program p)
{
DepthFirstIterator iter = new DepthFirstIterator(p);
int loop_number = 0;
while ( iter.hasNext() ) {
Object obj = iter.next();
if ( obj instanceof ForLoop )
insertTimingCalls ((ForLoop )obj, loop_number++);
}
}
private void insertTimingCalls (ForLoop loop, int number)
{
FunctionCall tic, toc;
tic = new FunctionCall(new Identifier(“cetus_tic”));
toc = new FunctionCall(new Identifier(“cetus_toc”));
tic.addArgument(new IntegerLiteral(number));
toc.addArgument(new IntegerLiteral(number));
CompoundStatement parent = (CompoundStatement )loop.getParent();
parent.addStatementBefore(loop, new ExpressionStatement(tic));
parent.addStatementAfter(loop, new ExpressionStatement
(toc));
}
}
ANALYSES AND TRANSFORMATIONS
Automatically instrumenting source programs is a commonly
used compiler capability. Figure 1 shows a basic
loop instrumenter that inserts timing calls around each
for loop in the given input program. Here we assume that
the function call cetus_tic(id) stores the current time
(get time of day, for example) with the given integer tag,
and cetus_toc(id) computes and stores the time difference
since the last call of cetus_tic(id).
At the end of an application run, basic runtime statistics
on the instrumented code sections can be generated
from this information.
int foo(void)
{
int i;
double t, s, a[100];
for ( i = 0; i < 50; ++i )
{
t = a[i];
a[i+50] = t + (a[i] + a[i+50])/2.0;
s = s + 2*a[i];
}
return 0;
}
(a)
int foo()
{
int i;
double t, s, a[100];
cetus_tic(0);
for (i = 0; i < 50; ++i)
{
t = a[i];
a[(i+50)] = (t + ((a[i] + a [(i+50)])/2.0));
s = (s + (2*a[i]));
}
cetus_toc(0);
return 0;
}
Original code
int a,b;
a = b;
a = b + c;
Modified Code
int a0,b0, a1, b1;
a0 = b0;
a1 = b1;
if (b0 != b1)
error();
a0 = b0 + c0;
a1 = b1 + c1;
if((b0!=b1)||(c0!=c1))
error();
Original code
int res,a;
res = search
(a);
…
int search
(int p)
{ int q;
…
q = p + 1;
…
return(1);
}
Modified code
int res0, res1, a0, a1;
search(a0, a1,
&res0, &res1);
…
void search(int p0,int
p1,int *r0,int *r1)
{ int q0, q1;
…
q0 = p0 + 1;
q1 = p1 + 1;
if (p0 != p1)
error();
…
*r0 = 1;
*r1 = 1;
return;
}