Академический Документы
Профессиональный Документы
Культура Документы
CODE GENERATION
5.1 Introduction
In order to generate executable code, usually the front-end compiler (i.e. the parser) will generate
an intermediate code, somewhat similar to assembly code, and then either an interpreter is used
to run this intermediate code or a suitable back-end compiler is used to generate the desired
machine code (from the intermediate code). The back-end compiler is always machine
dependent.
The two popularly used intermediate code language formats are the P-Code and the 3-Address
Code. In our discourse, we will only discuss the 3-address code.
<3-address code statem ent sequence> ::= [ <3-address code statem ent> ] [ <com m ent> ]
[ newline <3-address code statem ent sequence> ]
<3-address code statem ent> ::= <label> : [ <statem ent> ] | <statem ent>
<statem ent> ::= identifier = <unary or binary expression> | IF <condition> GOTO <label> |
GOTO <label> | <function call>
Introduction To Com piler Construction and Design © mofana mphaka Page -63-
Compiler Construction and Design – Intermediate Code Generation Page -64-
<param eter list call> ::= PARAMETER <id or value> newline [ <param eter list call> ]
<function invocation> ::= [ identifier = ] CALL <function nam e> , <num ber of param eters>
<function nam e> ::= identifier
<num ber of param eters> ::= natural num ber
Our 3-address code above does not offer a grammar of definitions: variable declarations and
function definitions. Variable declarations are (in C++) statements like
int x, y, z;
Although, it may not be difficult to offer a 3-address code for definitions, one may see that
definitions information would already be accessible from the symbol table! This information can
be accessed by the system functions like PARAMETER and CALL.
The reader should note that since PARAMETER pushes the corresponding parameter into the
stack, the calls to PARAMETER for arguments must be in reverse order so that the CALL
instruction will pop the arguments in correct order (for the corresponding function).
Example 5.1
Convert the following C++ code segment to 3-address code:
i = 1;
while (i <= 10)
{
foo = exp(10, i);
cout << foo << ‘\n’;
i++;
}
Solution
i=1
loop_body:
PARAMETER i
PARAMETER 10
foo = CALL exp, 2
Introduction To Com piler Construction and Design © mofana mphaka Page -64-
Compiler Construction and Design – Intermediate Code Generation Page -65-
PARAMETER ‘\n’
PARAMETER foo
CALL cout, 2
i = i + 1;
GOTO start
end_while:
We present below, a generic format in which one can easily generate a 3-address code for some
( C++) program segment. We do so by showing a generic way to generate a 3-address code for
the constructs: arrays (i.e. array indexing), if statement, while loop, for loop, do while loop and
a switch statement.
For example, if the array contains integers (i.e. int), then the base type is 4 bytes. That is, each
element occupies 4 bytes of memory. This means that the first element, say, array[0], starts at the
array offset and occupies the first 4 bytes. Then, the next element, arra[1] will start at (offset +1)
* 4.
Example 5.2
Generate a 3-address code for the following C++ code fragment which prints an array of 10
integer elements. The C++ code is
j = 0;
while (j < 10)
{
cout << arra[j] << ‘\n’;
j++;
}
Solution
A possible 3-address code could be:
j=0
Introduction To Com piler Construction and Design © mofana mphaka Page -65-
Compiler Construction and Design – Intermediate Code Generation Page -66-
PARAMETER ‘\n’
PARAMETER T1
CALL cout, 2
j=j+1
GOTO while
end_while:
if ( C )
S;
IF C’ GOTO S_start
else: GOTO end_if
S_start:
3-address code for S
end_if:
Example 5.3
Generate a 3-address code for the following C++ if construct.
if (prim e(n))
{
cout << n << “ is prim e \n”;
}
Solution
A possible 3-address code could be:
; First convert the condition to 3 address code – prim e(n)
PARAMETER n
T1 = CALL prim e, 1 ; T1 is the result of 3-address code conversion of prim e(n)
if_body: PARAMETER “ is prim e \n” ; This is the “body” of code that m ust be executed if the
Introduction To Com piler Construction and Design © mofana mphaka Page -66-
Compiler Construction and Design – Intermediate Code Generation Page -67-
end_if :
if ( ! C )
S;
we do
IF C’ GOTO end_if
else: 3-address code for S
end_if:
Example 5.4
Generate a 3-address code for the following C++ if construct with a negated condition.
if (! prim e(n))
{
cout << n << “ is NOT prim e \n”;
}
Solution
A possible 3-address code could be:
; First convert the POSITIVE condition part to 3 address code – prim e(n)
PARAMETER n
T1 = CALL prim e, 1
if: PARAMETER “ is NOT prim e \n” ; otherwise execute the if body, by default
PARAMETER n
CALL cout, 2
end_if:
Introduction To Com piler Construction and Design © mofana mphaka Page -67-
Compiler Construction and Design – Intermediate Code Generation Page -68-
E1 rel_opr E2
where rel_opr is one of the 3-address code relational operators. So, C is converted to 3-address
code as follows:
If E1 is not in 3-address code then convert it to 3-address code, E1' (otherwise rename it E1'),
also
If E2 is not in 3-address code then convert it to 3-address code, E2' (otherwise rename it E2').
Then
if ( C1 || C2 )
S;
we do
The above code uses the short circuit technique. That is, if the first condition, C1, evaluates to
true we execute S, no matter what the value of C2 is. We evaluate C2 only when C1 fails and,
again, execute S when C2 evaluates to true, otherwise we skip S (i.e. GOTO exit).
Example 5.5
Generate a 3-address code for the following C++ if construct with a disjunction condition.
if (ch == ‘y’ || ch == ‘Y’)
{
cout << “Enter next num ber -> ”;
Introduction To Com piler Construction and Design © mofana mphaka Page -68-
Compiler Construction and Design – Intermediate Code Generation Page -69-
Solution
A possible 3-address code could be:
; Convert to 3 address & evaluate the first condition and if true execute the if body
; Otherwise, convert to 3 address & evaluate the next condition and if true execute the if
; body
end_if :
if ( C1 && C2 )
S;
we do
Introduction To Com piler Construction and Design © mofana mphaka Page -69-
Compiler Construction and Design – Intermediate Code Generation Page -70-
Example 5.6
Generate a 3-address code for the following C++ if construct with a disjunction condition.
if (OW M >= 60 && OW M < 70)
{
owm Grade = ‘C’;
recom m endation = “Second Class – Second Division”;
}
Solution
A possible 3-address code could be:
IF OW M >= 60 GOTO next_cond ; If first condition holds then check the next one
else: GOTO end_if ; otherwise the whole conjunction is false – exit
end_if :
if ( C )
S1;
else
S2;
we do
IF C’ GOTO S1_start
else: 3-address code for S2 ; The “else” part is by default
GOTO end_if
S1_start:
3-address code for S1
end_if:
Introduction To Com piler Construction and Design © mofana mphaka Page -70-
Compiler Construction and Design – Intermediate Code Generation Page -71-
Example 5.7
Generate a 3-address code for the following C++ if-else construct.
if (m ark >= 50
status = “Pass”;
else
status = “Fail”;
Solution
A possible 3-address code could be:
IF m ark >= 50 GOTO if_body ; condition holds – go to the “if” part
end_if :
if ( C1 && C2 )
S1;
else
S2
we do
Introduction To Com piler Construction and Design © mofana mphaka Page -71-
Compiler Construction and Design – Intermediate Code Generation Page -72-
if ( C1 || C2 )
S1;
else
S2
we do
S1_start:
3-address code for S
end_if:
Example 5.8
Generate a 3-address code for the following C++ if-else construct, with a conjunction.
if ((m ark >= 50) && (m ark <= 100)
status = “Pass”;
else
status = “Fail”;
Solution
A possible 3-address code could be:
IF m ark >= 50 GOTO next_conjunct
next_conjunct:
IF m ark <= 100 GOTO if_body
GOTO else
Introduction To Com piler Construction and Design © mofana mphaka Page -72-
Compiler Construction and Design – Intermediate Code Generation Page -73-
end_if :
if ( C1 )
S1;
else if ( C2 )
S2;
else
S3;
we do
Example 5.9
Generate a 3-address code for the following C++ nested If-else if-else construct.
if (OW M >= 60
recom m endation = “Pass with Distinction”;
else if (OW M >= 50
recom m endation = “Pass;
else
recom m endation = “Fail;
Solution
A possible 3-address code could be:
IF OW M >= 60 GOTO if_body ; condition holds – go to the “if” part
IF OW M >= 50 GOTO else_if_body ; condition for “else if” holds – go to the “else if”
Introduction To Com piler Construction and Design © mofana mphaka Page -73-
Compiler Construction and Design – Intermediate Code Generation Page -74-
part
else: recom m endation = “Fail; ; Default code for the “else” part
GOTO end_if
else_if_body :
recom m endation = “Pass”
end_if :
if ( C1 )
S1;
else if ( C2 )
S2;
else if ( C3 )
S3;
!
if ( Cn-1 )
Sn-1;
else
Sn;
we do
S1_start:
3-address code for S1
GOTO end_if
S2_start:
Introduction To Com piler Construction and Design © mofana mphaka Page -74-
Compiler Construction and Design – Intermediate Code Generation Page -75-
Example 5.10
Generate a 3-address code for the following C++ nested If-else if-else construct.
if ( m ark >= 80)
grade = ‘A’;
else if (m ark >= 70)
grade = ‘B’;
else if (m ark >= 60)
grade = ‘C’;
else if (m ark >= 50)
grade = ‘D’;
else if (m ark >= 40)
grade = ‘E’;
else
grade = ‘F’;
Solution
A possible 3-address code could be:
IF m ark >= 80 GOTO if_body
else_if_body1 :
grade = ‘B’
Introduction To Com piler Construction and Design © mofana mphaka Page -75-
Compiler Construction and Design – Intermediate Code Generation Page -76-
GOTO end_if
else_if_body2 :
grade = ‘C’
GOTO end_if
else_if_body3 :
grade = ‘D’
GOTO end_if
else_if_body4 :
grade = ‘E’
end_if :
Example 5.11
Generate a 3-address code for the following C++ code segment:
if (x >= 0 && y != 0)
cout << “The quotient “ << x << “ / “ << y << “ = ” << x / y << “\n”;
else if (y == 0)
cout << “Divide by zero error: the denom inator is zero!\n”;
else
cout << “The enum erator is negative!\n”;
Solution
One possible code could be:
PARAMETER “The enum erator is negative!\n” ; The default code for the “else” part
CALL cout, 1
GOTO end_if
next_conjunct:
IF y != 0 GOTO if_body
GOTO else_if ; the whole conjunction has failed – check else if
if_body:
PARAMETER “\n”
T1 = x / y
PARAMETER T1
PARAMETER “=”
PARAMETER y
PARAMETER “/”
PARAMETER x
PARAMETER “The quotient”
Introduction To Com piler Construction and Design © mofana mphaka Page -76-
Compiler Construction and Design – Intermediate Code Generation Page -77-
CALL cout, 7
GOTO end_if
else_if_body:
PARAMETER “Divide by zero error: the denom inator is zero!\n”
CALL cout, 1
end_if:
while ( C )
S;
S_start:
S; // a labelled statem ent, which starts the code block of S
goto start; // loop back to the testing statem ent, if ...
exit: // an em pty labelled statem ent
Introduction To Com piler Construction and Design © mofana mphaka Page -77-
Compiler Construction and Design – Intermediate Code Generation Page -78-
expr1;
while( expr2)
{
S;
expr3;
}
So, to generate a 3-address code for a for loop, one proceeds as follows:
do
S;
while ( C );
S;
while( C )
S;
So, to generate a 3-address code for a do while loop, one proceeds as follows:
Introduction To Com piler Construction and Design © mofana mphaka Page -78-
Compiler Construction and Design – Intermediate Code Generation Page -79-
The above algorithm notwithstanding, we can generate an efficient code if we observe that
S;
while ( C )
S;
S_start:
S;
if ( C ) goto S_start ;
Exit: ;
S_start:
3-address code for S
Covert C to 3-address code, C’
if ( C’ ) goto S_start
Exit:
The following example shows how, typically one would generate a 3-address code for a “while”
loop and/or a “do-while” loop.
Example 5.12
Generate a possible 3 address code for the following C++ code segment:
double biggest, next;
char ch = ‘Y’;
do
{
cout << “Anym ore num bers to read? [Y/N] “;
cin >> ch;
ch = upcase(ch); // convert ch to upper case
}
while ((ch != ‘Y’) && (ch != ‘N’));
Introduction To Com piler Construction and Design © mofana mphaka Page -79-
Compiler Construction and Design – Intermediate Code Generation Page -80-
}
cout << “The biggest num ber is “ << biggest << “\n”;
Solution
A possible code could be:
ch = ‘Y’
PARAMETER “Enter the first num ber “
CALL cout, 1
biggest = CALL cin, 0
while:
IF ch == ‘Y’ GOTO while_body
GOTO end_while
while_body:
PARAMETER “Enter the next num ber “
CALL cout, 1
next = CALL cin, 0
if_body:
biggest = next
end_if:
do_while:
PARAMETER “Anym ore num bers to read? [Y/N] “ ;
CALL cout, 1
ch = CALL cin, 0
PARAMETER ch
ch = CALL upcase, 1 ; convert ch to upper case
next_cond:
IF ch != ‘N’ GOTO do_while
end_do_while:
GOTO while
end_while:
PARAMETER ““\n”
PARAMETER biggest
PARAMETER “The biggest num ber is “
CALL cout, 3
Introduction To Com piler Construction and Design © mofana mphaka Page -80-
Compiler Construction and Design – Intermediate Code Generation Page -81-
Example 5.13
Generate a possible 3 address code for the following C++ code segment:
i = 0;
j = 10;
Assume that there exist functions to covert numbers from one base to the other. E.g
Solution
A possible code could be:
i=0
j = 10
while:
IF i < 10 GOTO while_body
PARAMETER Tij
Tdec = CALL decim al, 1 ; convert the result to binary
Introduction To Com piler Construction and Design © mofana mphaka Page -81-
Compiler Construction and Design – Intermediate Code Generation Page -82-
IF Tdec !=0 GOTO else_if_body ; if the result is true then execute else if body
next_conjunct: ; in the 2 nd conjunct the two num bers, i and j are ANDed
PARAMETER I ; bitwise
Ti = CALL binary, 1
PARAMETER j
Tj = CALL binary, 1
Tij = Ti * Tj
PARAMETER Tij
Tdec = CALL decim al, 1
IF Tdec !=0 GOTO if_body
GOTO else_if
if_body:
PARAMETER “i and j are even, identical and positive”
CALL cout, 1
end_if:
i=i+1
j=j-1
GOTO while
end_while:
switch ( E )
{
case V1 : S1; break;
case V2 : S2; break;
case V3 : S3; break;
...
case Vn : Sn; break;
default : S
}
if (E == V1) S1;
else if (E == V2) S2;
else if (E == V3) S3;
Introduction To Com piler Construction and Design © mofana mphaka Page -82-
Compiler Construction and Design – Intermediate Code Generation Page -83-
...
else if (E == Vn) Sn;
else S;
IF E’ == V1 GOTO S1_start
IF E’ == V2 GOTO S2_start
IF E’ == V3 GOTO S3_start
...
IF E’ == Vn GOTO Sn_start
3-address code for S ; this is the default else statement: else S;
GOTO exit
...
GOTO exit
Sn_start: 3-address code for Sn
exit:
5.3 Exercises
1. Generate a possible 3-address code for the following C++ code segment. The code prints
elements of an integer (i.e. int array[10]) array of 10 elements:
Introduction To Com piler Construction and Design © mofana mphaka Page -83-
Compiler Construction and Design – Intermediate Code Generation Page -84-
Assume that there exist functions to covert numbers from one base to the other. E.g
3. Generate a possible 3-address code for the following C++ code segment.
4. Generate a possible 3-address code for the following C++ code segment.
do
{
cout << “Enter a natural num ber to test with => “;
cin >> n;
if ( prim e(n) )
cout << n << “ is prim e!\n”;
else if ( n % 2 != 0)
cout << n << “ is odd!\n”;
else
cout << n << “ is even!\n”;
Introduction To Com piler Construction and Design © mofana mphaka Page -84-
Compiler Construction and Design – Intermediate Code Generation Page -85-
5. Generate a possible 3 address code for the following C++ code segment, that sorts an array
of real numbers (i.e. float item[]):
bool sorted = false; // Start by assum ing that the list of item s is not yet sorted
while (!sorted) // while (the list is) not sorted – !sorted
{
sorted = true; // sort the list as follows:
for(int i = 1; i < n; i++) // traverse the entire list
if (item [i] > item [i+1]) // if at any instance, item [i] > item [i+1] then
{
swap(item [i], item [i+1]); // swap the two item s – a call to function swap
sorted = false; // and record that the list is not yet sorted and repeat
}
}
Introduction To Com piler Construction and Design © mofana mphaka Page -85-